fix: ui polish (#79)

* fix: change label of language to primary language spoken

* fix: add labels to top of empty states

* fix: add help text to name field in editable or empty states

* fix: move repeated messages into separate files

* fix: translate missed string
This commit is contained in:
Adam Butterworth
2019-03-12 17:14:22 -04:00
committed by GitHub
parent 01bdc66528
commit a58f0804a7
12 changed files with 142 additions and 91 deletions

View File

@@ -191,7 +191,7 @@ export class ProfilePage extends React.Component {
{...commonFormProps}
/>
</Col>
<Col md={8} className="pt-md-3">
<Col md={8} lg={{ size: 8, offset: 1 }} className="pt-md-3">
{shouldShowAgeMessage ? <AgeMessage accountURL="#account" /> : null}
<Bio
bio={bio}

View File

@@ -94,13 +94,16 @@ class Bio extends React.Component {
</React.Fragment>
),
empty: (
<EmptyContent onClick={this.handleOpen}>
<FormattedMessage
id="profile.bio.empty"
defaultMessage="Add a short bio"
description="instructions when the user hasn't written an About Me"
/>
</EmptyContent>
<React.Fragment>
<EditableItemHeader content={intl.formatMessage(messages['profile.bio.about.me'])} />
<EmptyContent onClick={this.handleOpen}>
<FormattedMessage
id="profile.bio.empty"
defaultMessage="Add a short bio"
description="instructions when the user hasn't written an About Me"
/>
</EmptyContent>
</React.Fragment>
),
static: (
<React.Fragment>

View File

@@ -148,7 +148,7 @@ class Certificates extends React.Component {
</React.Fragment>
),
empty: (
<div>
<React.Fragment>
<EditableItemHeader
content={intl.formatMessage(messages['profile.certificates.my.certificates'])}
showEditButton
@@ -157,7 +157,7 @@ class Certificates extends React.Component {
visibility={visibilityCourseCertificates}
/>
{this.renderCertificates()}
</div>
</React.Fragment>
),
static: (
<React.Fragment>

View File

@@ -2,7 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Form, FormFeedback, FormGroup, Input, Label } from 'reactstrap';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { injectIntl, intlShape } from 'react-intl';
import messages from './Country.messages';
// Components
import FormControls from './elements/FormControls';
@@ -49,7 +51,7 @@ class Country extends React.Component {
render() {
const {
formId, country, visibilityCountry, editMode, saveState, error,
formId, country, visibilityCountry, editMode, saveState, error, intl,
} = this.props;
return (
@@ -62,11 +64,7 @@ class Country extends React.Component {
<Form onSubmit={this.handleSubmit}>
<FormGroup>
<Label for="country" id={`${formId}-label`}>
<FormattedMessage
id="profile.country.label"
defaultMessage="Location"
description="Location form label"
/>
{intl.formatMessage(messages['profile.country.label'])}
</Label>
<Input
type="select"
@@ -97,7 +95,7 @@ class Country extends React.Component {
editable: (
<React.Fragment>
<EditableItemHeader
content="Location"
content={intl.formatMessage(messages['profile.country.label'])}
showEditButton
onClickEdit={this.handleOpen}
showVisibility={visibilityCountry !== null}
@@ -107,17 +105,20 @@ class Country extends React.Component {
</React.Fragment>
),
empty: (
<EmptyContent onClick={this.handleOpen}>
<FormattedMessage
id="profile.country.empty"
defaultMessage="Add location"
description="instructions when the user doesn't have a location set"
<React.Fragment>
<EditableItemHeader
content={intl.formatMessage(messages['profile.country.label'])}
/>
</EmptyContent>
<EmptyContent onClick={this.handleOpen}>
{intl.formatMessage(messages['profile.country.empty'])}
</EmptyContent>
</React.Fragment>
),
static: (
<React.Fragment>
<EditableItemHeader content="Location" />
<EditableItemHeader
content={intl.formatMessage(messages['profile.country.label'])}
/>
<p className="h5">{ALL_COUNTRIES[country]}</p>
</React.Fragment>
),
@@ -146,6 +147,9 @@ Country.propTypes = {
submitHandler: PropTypes.func.isRequired,
closeHandler: PropTypes.func.isRequired,
openHandler: PropTypes.func.isRequired,
// i18n
intl: intlShape.isRequired,
};
Country.defaultProps = {
@@ -159,4 +163,4 @@ Country.defaultProps = {
export default connect(
editableFormSelector,
{},
)(Country);
)(injectIntl(Country));

View File

@@ -0,0 +1,16 @@
import { defineMessages } from 'react-intl';
const messages = defineMessages({
'profile.country.label': {
id: 'profile.country.label',
defaultMessage: 'Location',
description: 'The label for a country in a user profile.',
},
'profile.country.empty': {
id: 'profile.country.empty',
defaultMessage: 'Add location',
description: 'The affordance to add country location to a users profile.',
},
});
export default messages;

View File

@@ -105,13 +105,16 @@ class Education extends React.Component {
</React.Fragment>
),
empty: (
<EmptyContent onClick={this.handleOpen}>
<FormattedMessage
id="profile.education.empty"
defaultMessage="Add education"
description="instructions when the user doesn't have their level of education set"
/>
</EmptyContent>
<React.Fragment>
<EditableItemHeader content={intl.formatMessage(messages['profile.education.education'])} />
<EmptyContent onClick={this.handleOpen}>
<FormattedMessage
id="profile.education.empty"
defaultMessage="Add education"
description="instructions when the user doesn't have their level of education set"
/>
</EmptyContent>
</React.Fragment>
),
static: (
<React.Fragment>

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Form, FormFeedback, FormGroup, FormText, Input, Label } from 'reactstrap';
import { connect } from 'react-redux';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { injectIntl, intlShape } from 'react-intl';
import messages from './Name.messages';
@@ -60,7 +60,9 @@ class Name extends React.Component {
<div role="dialog" aria-labelledby={`${formId}-label`}>
<Form onSubmit={this.handleSubmit}>
<FormGroup>
<Label for="name" id={`${formId}-label`}>Full Name</Label>
<Label for="name" id={`${formId}-label`}>
{intl.formatMessage(messages['profile.name.full.name'])}
</Label>
<Input
type="text"
id={formId}
@@ -71,11 +73,7 @@ class Name extends React.Component {
aria-describedby={`${formId}-error-feedback ${formId}-help-text`}
/>
<FormText id={`${formId}-help-text`}>
<FormattedMessage
id="profile.name.details"
defaultMessage="This is the name that appears in your account and on your certificates."
description="describes the area for the user to update their name"
/>
{intl.formatMessage(messages['profile.name.details'])}
</FormText>
<FormFeedback id={`${formId}-error-feedback`}>{error}</FormFeedback>
</FormGroup>
@@ -99,16 +97,21 @@ class Name extends React.Component {
visibility={visibilityName}
/>
<p className="h5">{name}</p>
<FormText>
{intl.formatMessage(messages['profile.name.details'])}
</FormText>
</React.Fragment>
),
empty: (
<EmptyContent onClick={this.handleOpen}>
<FormattedMessage
id="profile.name.empty"
defaultMessage="Add name"
description="instructions when the user hasn't entered their name"
/>
</EmptyContent>
<React.Fragment>
<EditableItemHeader content={intl.formatMessage(messages['profile.name.full.name'])} />
<EmptyContent onClick={this.handleOpen}>
{intl.formatMessage(messages['profile.name.empty'])}
</EmptyContent>
<FormText>
{intl.formatMessage(messages['profile.name.details'])}
</FormText>
</React.Fragment>
),
static: (
<React.Fragment>

View File

@@ -6,6 +6,16 @@ const messages = defineMessages({
defaultMessage: 'Full Name',
description: 'A section of a user profile',
},
'profile.name.details': {
id: 'profile.name.details',
defaultMessage: 'This is the name that appears in your account and on your certificates.',
description: 'Describes the area for a user to update their name.',
},
'profile.name.empty': {
id: 'profile.name.empty',
defaultMessage: 'Add name',
description: 'The affordance to add a name to a users profile.',
},
});
export default messages;

View File

@@ -2,7 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Form, FormFeedback, FormGroup, Input, Label } from 'reactstrap';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { injectIntl, intlShape } from 'react-intl';
import messages from './PreferredLanguage.messages';
// Components
import FormControls from './elements/FormControls';
@@ -57,7 +59,13 @@ class PreferredLanguage extends React.Component {
render() {
const {
formId, languageProficiencies, visibilityLanguageProficiencies, editMode, saveState, error,
formId,
languageProficiencies,
visibilityLanguageProficiencies,
editMode,
saveState,
error,
intl,
} = this.props;
const value = languageProficiencies.length ? languageProficiencies[0].code : '';
@@ -72,11 +80,7 @@ class PreferredLanguage extends React.Component {
<Form onSubmit={this.handleSubmit}>
<FormGroup>
<Label for={formId} id={`${formId}-label`}>
<FormattedMessage
id="profile.preferredlanguage.label"
defaultMessage="Language"
description="Preferred language label"
/>
{intl.formatMessage(messages['profile.preferredlanguage.label'])}
</Label>
<Input
type="select"
@@ -107,13 +111,7 @@ class PreferredLanguage extends React.Component {
editable: (
<React.Fragment>
<EditableItemHeader
content={(
<FormattedMessage
id="profile.preferredlanguage.label"
defaultMessage="Language"
description="Preferred language label"
/>
)}
content={intl.formatMessage(messages['profile.preferredlanguage.label'])}
showEditButton
onClickEdit={this.handleOpen}
showVisibility={visibilityLanguageProficiencies !== null}
@@ -123,24 +121,19 @@ class PreferredLanguage extends React.Component {
</React.Fragment>
),
empty: (
<EmptyContent onClick={this.handleOpen}>
<FormattedMessage
id="profile.preferredlanguage.empty"
defaultMessage="Add language"
description="instructions when the user doesn't have a location set"
<React.Fragment>
<EditableItemHeader
content={intl.formatMessage(messages['profile.preferredlanguage.label'])}
/>
</EmptyContent>
<EmptyContent onClick={this.handleOpen}>
{intl.formatMessage(messages['profile.preferredlanguage.empty'])}
</EmptyContent>
</React.Fragment>
),
static: (
<React.Fragment>
<EditableItemHeader
content={(
<FormattedMessage
id="profile.preferredlanguage.label"
defaultMessage="Language"
description="Preferred language label"
/>
)}
content={intl.formatMessage(messages['profile.preferredlanguage.label'])}
/>
<p className="h5">{ALL_LANGUAGES[value]}</p>
</React.Fragment>
@@ -175,6 +168,9 @@ PreferredLanguage.propTypes = {
submitHandler: PropTypes.func.isRequired,
closeHandler: PropTypes.func.isRequired,
openHandler: PropTypes.func.isRequired,
// i18n
intl: intlShape.isRequired,
};
PreferredLanguage.defaultProps = {
@@ -188,4 +184,4 @@ PreferredLanguage.defaultProps = {
export default connect(
editableFormSelector,
{},
)(PreferredLanguage);
)(injectIntl(PreferredLanguage));

View File

@@ -0,0 +1,16 @@
import { defineMessages } from 'react-intl';
const messages = defineMessages({
'profile.preferredlanguage.empty': {
id: 'profile.preferredlanguage.empty',
defaultMessage: 'Add language',
description: 'Instructions when the user doesnt have a preferred language set.',
},
'profile.preferredlanguage.label': {
id: 'profile.preferredlanguage.label',
defaultMessage: 'Primary Language Spoken',
description: 'The label for a users primary spoken language.',
},
});
export default messages;

View File

@@ -101,15 +101,18 @@ class SocialLinks extends React.Component {
expression={editMode}
cases={{
empty: (
<ul className="list-unstyled">
{socialLinks.map(({ platform }) => (
<EmptyListItem
key={platform}
onClick={this.handleOpen}
name={platformDisplayInfo[platform].name}
/>
))}
</ul>
<React.Fragment>
<EditableItemHeader content={intl.formatMessage(messages['profile.sociallinks.social.links'])} />
<ul className="list-unstyled">
{socialLinks.map(({ platform }) => (
<EmptyListItem
key={platform}
onClick={this.handleOpen}
name={platformDisplayInfo[platform].name}
/>
))}
</ul>
</React.Fragment>
),
static: (
<React.Fragment>

View File

@@ -1,6 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlus } from '@fortawesome/free-solid-svg-icons';
@@ -17,16 +16,14 @@ function EmptyContent({ children, onClick, showPlusIcon }) {
return (
<div>
{onClick ? (
<Button
type="button"
color="link"
block
className="pl-0 text-left"
<a
role="button"
className="pl-0 text-left d-block"
{...interactiveProps}
>
{showPlusIcon ? <FontAwesomeIcon size="xs" className="mr-2" icon={faPlus} /> : null}
{children}
</Button>
</a>
) : children}
</div>
);