Add basic profile editor
This commit is contained in:
parent
6db6793b8b
commit
f2b1305ce9
5 changed files with 133 additions and 4 deletions
|
@ -25,7 +25,6 @@ export function fetchMe() {
|
|||
|
||||
api(getState).get('/api/v1/accounts/verify_credentials').then(response => {
|
||||
dispatch(fetchMeSuccess(response.data));
|
||||
dispatch(importFetchedAccount(response.data));
|
||||
}).catch(error => {
|
||||
dispatch(fetchMeFail(error));
|
||||
});
|
||||
|
@ -34,6 +33,7 @@ export function fetchMe() {
|
|||
|
||||
export function patchMe(params) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(patchMeRequest());
|
||||
return api(getState)
|
||||
.patch('/api/v1/accounts/update_credentials', params)
|
||||
.then(response => {
|
||||
|
@ -51,9 +51,12 @@ export function fetchMeRequest() {
|
|||
}
|
||||
|
||||
export function fetchMeSuccess(me) {
|
||||
return {
|
||||
type: ME_FETCH_SUCCESS,
|
||||
me,
|
||||
return (dispatch, getState) => {
|
||||
dispatch(importFetchedAccount(me));
|
||||
dispatch({
|
||||
type: ME_FETCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
87
app/gabsocial/features/edit_profile/index.js
Normal file
87
app/gabsocial/features/edit_profile/index.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Column from '../ui/components/column';
|
||||
import {
|
||||
SimpleForm,
|
||||
FieldsGroup,
|
||||
TextInput,
|
||||
} from 'gabsocial/features/forms';
|
||||
import { patchMe } from 'gabsocial/actions/me';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.edit_profile', defaultMessage: 'Edit profile' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const me = state.get('me');
|
||||
return {
|
||||
account: state.getIn(['accounts', me]),
|
||||
};
|
||||
};
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class EditProfile extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { isLoading: false };
|
||||
}
|
||||
|
||||
getFormData = (form) => {
|
||||
return Object.fromEntries(
|
||||
new FormData(form).entries()
|
||||
);
|
||||
}
|
||||
|
||||
handleSubmit = (event) => {
|
||||
const { dispatch } = this.props;
|
||||
const formData = this.getFormData(event.target);
|
||||
dispatch(patchMe(formData)).then(() => {
|
||||
this.setState({ isLoading: false });
|
||||
}).catch((error) => {
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
this.setState({ isLoading: true });
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props;
|
||||
|
||||
return (
|
||||
<Column icon='users' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
<SimpleForm onSubmit={this.handleSubmit}>
|
||||
<fieldset disabled={this.state.isLoading}>
|
||||
<FieldsGroup>
|
||||
<TextInput
|
||||
label='Display name'
|
||||
name='display_name'
|
||||
defaultValue={account.get('display_name')}
|
||||
/>
|
||||
<TextInput
|
||||
label='Bio'
|
||||
name='note'
|
||||
defaultValue={account.get('bio')}
|
||||
/>
|
||||
</FieldsGroup>
|
||||
</fieldset>
|
||||
<div className='actions'>
|
||||
<button name='button' type='submit' className='btn button button-primary'>Save changes</button>
|
||||
</div>
|
||||
</SimpleForm>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -184,3 +184,36 @@ export class SelectDropdown extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
export class TextInput extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
label: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
defaultValue: PropTypes.string,
|
||||
maxLength: PropTypes.number,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { label, name, defaultValue, maxLength } = this.props;
|
||||
|
||||
return (
|
||||
<div className='input with_label string optional'>
|
||||
<div className='label_input'>
|
||||
<label className='string optional' htmlFor={name}>{label}</label>
|
||||
<div className='label_input__wrapper'>
|
||||
<input
|
||||
maxlength={maxLength}
|
||||
className='string optional'
|
||||
size={maxLength}
|
||||
type='text'
|
||||
defaultValue={defaultValue}
|
||||
name={name}
|
||||
id={name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ import {
|
|||
// GroupEdit,
|
||||
LoginPage,
|
||||
Preferences,
|
||||
EditProfile,
|
||||
} from './util/async-components';
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
|
@ -236,6 +237,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
|
||||
|
||||
<WrappedRoute path='/settings/preferences' layout={LAYOUT.DEFAULT} component={Preferences} content={children} />
|
||||
<WrappedRoute path='/settings/profile' layout={LAYOUT.DEFAULT} component={EditProfile} content={children} />
|
||||
|
||||
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />
|
||||
</Switch>
|
||||
|
|
|
@ -165,3 +165,7 @@ export function LoginPage() {
|
|||
export function Preferences() {
|
||||
return import(/* webpackChunkName: "features/preferences" */'../../preferences');
|
||||
}
|
||||
|
||||
export function EditProfile() {
|
||||
return import(/* webpackChunkName: "features/edit_profile" */'../../edit_profile');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue