Merge pull request #530 from sharetribe/profile-bio

Add bio to profile
This commit is contained in:
Kimmo Puputti 2017-11-03 09:43:16 +02:00 committed by GitHub
commit 9efd7093d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 123 additions and 19 deletions

View file

@ -14,3 +14,10 @@
.inputError {
border-bottom-color: var(--failColor);
}
.textarea {
@media (--viewportMedium) {
/* Fix baseline alignment */
padding-top: 6px;
}
}

View file

@ -46,6 +46,7 @@ class TextInputFieldComponent extends Component {
const inputClasses = classNames(css.input, {
[css.inputSuccess]: valid,
[css.inputError]: hasError,
[css.textarea]: isTextarea,
});
const inputProps = isTextarea
? { className: inputClasses, id, ...input, ...rest }

View file

@ -40,7 +40,7 @@ exports[`EditListingDescriptionForm matches snapshot 1`] = `
Describe your sauna
</label>
<textarea
className=""
className="undefined"
id="fakeTestForm.description"
name="description"
onBlur={[Function]}

View file

@ -15,7 +15,7 @@
.sectionContainer {
padding: 0;
margin-bottom: 36px;
margin-bottom: 37px;
@media (--viewportMedium) {
padding: 0;
@ -29,6 +29,7 @@
margin-top: 0;
margin-bottom: 13px;
@media (--viewportMedium) {
margin-top: 0;
margin-bottom: 20px;
@ -36,9 +37,18 @@
}
.lastSection {
margin-bottom: 66px;
/* Fix baseline alignment */
padding-top: 3px;
margin-bottom: 69px;
@media (--viewportMedium) {
padding-top: 6px;
margin-bottom: 111px;
& .sectionTitle {
margin-bottom: 18px;
}
}
}
@ -276,6 +286,15 @@
width: calc(66% - 9px);
}
.bioInfo {
color: var(--matterColorAnti);
margin-top: 11px;
@media (--viewportMedium) {
margin-top: 13px;
}
}
.submitButton {
margin-top: 24px;
}

View file

@ -146,6 +146,14 @@ class ProfileSettingsFormComponent extends Component {
});
const lastNameRequired = validators.required(lastNameRequiredMessage);
// Bio
const bioLabel = intl.formatMessage({
id: 'ProfileSettingsForm.bioLabel',
});
const bioPlaceholder = intl.formatMessage({
id: 'ProfileSettingsForm.bioPlaceholder',
});
const uploadingOverlay =
uploadInProgress || this.state.uploadDelay ? (
<div className={css.uploadingImageOverlay}>
@ -241,7 +249,7 @@ class ProfileSettingsFormComponent extends Component {
<FormattedMessage id="ProfileSettingsForm.fileInfo" />
</div>
</div>
<div className={classNames(css.sectionContainer, css.lastSection)}>
<div className={css.sectionContainer}>
<h3 className={css.sectionTitle}>
<FormattedMessage id="ProfileSettingsForm.yourName" />
</h3>
@ -266,6 +274,21 @@ class ProfileSettingsFormComponent extends Component {
/>
</div>
</div>
<div className={classNames(css.sectionContainer, css.lastSection)}>
<h3 className={css.sectionTitle}>
<FormattedMessage id="ProfileSettingsForm.bioHeading" />
</h3>
<TextInputField
type="textarea"
name="bio"
id={`${form}.bio`}
label={bioLabel}
placeholder={bioPlaceholder}
/>
<p className={css.bioInfo}>
<FormattedMessage id="ProfileSettingsForm.bioInfo" />
</p>
</div>
{submitError}
<Button
className={css.submitButton}

View file

@ -12,3 +12,32 @@
margin: 56px auto;
}
}
.headingContainer {
display: flex;
flex-direction: row;
}
.heading {
margin-right: 24px;
}
.profileLink {
@apply --marketplaceButtonStylesSecondary;
@apply --marketplaceH5FontStyles;
display: inline-block;
width: auto;
min-height: auto;
height: 41px;
float: right;
flex-shrink: 0;
margin: 19px 0 0 auto;
padding: 9px 16px 8px 16px;
@media (--viewportMedium) {
margin: 37px 0 0 auto;
}
}

View file

@ -14,6 +14,7 @@ import {
LayoutWrapperMain,
LayoutWrapperFooter,
Footer,
NamedLink,
} from '../../components';
import { ProfileSettingsForm, TopbarContainer } from '../../containers';
@ -48,15 +49,19 @@ export class ProfileSettingsPageComponent extends Component {
} = this.props;
const handleSubmit = values => {
const { firstName, lastName } = values;
const name = { firstName, lastName };
const { firstName, lastName, bio: rawBio } = values;
// Ensure that the optional bio is a string
const bio = rawBio || '';
const profile = { firstName, lastName, bio };
const uploadedImage = this.props.image;
// Update profileImage only if file system has been accessed
const updatedValues =
uploadedImage && uploadedImage.imageId && uploadedImage.file
? { ...name, profileImageId: uploadedImage.imageId }
: name;
? { ...profile, profileImageId: uploadedImage.imageId }
: profile;
onUpdateProfile(updatedValues).then(() => {
this.setState({ profileUpdated: true });
@ -69,7 +74,7 @@ export class ProfileSettingsPageComponent extends Component {
};
const user = ensureCurrentUser(currentUser);
const { firstName, lastName } = user.attributes.profile;
const { firstName, lastName, bio } = user.attributes.profile;
const profileImageId = user.profileImage ? user.profileImage.id : null;
const profileImage = image || { imageId: profileImageId };
@ -77,7 +82,7 @@ export class ProfileSettingsPageComponent extends Component {
<ProfileSettingsForm
className={css.form}
currentUser={currentUser}
initialValues={{ firstName, lastName, profileImage }}
initialValues={{ firstName, lastName, bio, profileImage }}
profileImage={profileImage}
onImageUpload={e => onImageUploadHandler(e, onImageUpload)}
uploadInProgress={uploadInProgress}
@ -104,9 +109,20 @@ export class ProfileSettingsPageComponent extends Component {
</LayoutWrapperTopbar>
<LayoutWrapperMain>
<div className={css.content}>
<h1>
<FormattedMessage id="ProfileSettingsPage.title" />
</h1>
<div className={css.headingContainer}>
<h1 className={css.heading}>
<FormattedMessage id="ProfileSettingsPage.title" />
</h1>
{user.id ? (
<NamedLink
className={css.profileLink}
name="ProfilePage"
params={{ id: user.id.uuid }}
>
<FormattedMessage id="ProfileSettingsPage.viewProfileLink" />
</NamedLink>
) : null}
</div>
{profileSettingsForm}
</div>
</LayoutWrapperMain>

View file

@ -28,12 +28,14 @@ exports[`ContactDetailsPage matches snapshot 1`] = `
rootClassName={null}
>
<div>
<h1>
<FormattedMessage
id="ProfileSettingsPage.title"
values={Object {}}
/>
</h1>
<div>
<h1>
<FormattedMessage
id="ProfileSettingsPage.title"
values={Object {}}
/>
</h1>
</div>
</div>
</LayoutWrapperMain>
<LayoutWrapperFooter

View file

@ -397,6 +397,10 @@
"ProfilePage.schemaTitle": "{name} | {siteTitle}",
"ProfileSettingsForm.addYourProfilePicture": "+ Add your profile picture…",
"ProfileSettingsForm.addYourProfilePictureMobile": "+ Add",
"ProfileSettingsForm.bioHeading": "Your profile bio",
"ProfileSettingsForm.bioInfo": "Saunatime is built on relationships. Help other people get to know you.",
"ProfileSettingsForm.bioLabel": "Bio",
"ProfileSettingsForm.bioPlaceholder": "Tell us a little bit about yourself…",
"ProfileSettingsForm.changeAvatar": "Change",
"ProfileSettingsForm.fileInfo": ".JPG, .GIF or .PNG max. 10 MB",
"ProfileSettingsForm.firstNameLabel": "First name",
@ -413,6 +417,7 @@
"ProfileSettingsForm.yourName": "Your name",
"ProfileSettingsForm.yourProfilePicture": "Your profile picture",
"ProfileSettingsPage.title": "Profile settings",
"ProfileSettingsPage.viewProfileLink": "View your profile",
"ResponsiveImage.noImage": "No image",
"SaleDetailsPanel.acceptSaleFailed": "Oops, accepting failed. Please try again.",
"SaleDetailsPanel.bannedUserDisplayName": "Banned user",

View file

@ -75,6 +75,7 @@ export const currentUser = shape({
lastName: string.isRequired,
displayName: string.isRequired,
abbreviatedName: string.isRequired,
bio: string,
}).isRequired,
stripeConnected: bool.isRequired,
}),
@ -89,6 +90,7 @@ export const user = shape({
profile: shape({
displayName: string.isRequired,
abbreviatedName: string.isRequired,
bio: string,
}),
}),
});