refactor: updated frontend-build & resolved eslint issues (#654)
Co-authored-by: Bilal Qamar <59555732+BilalQamar95@users.noreply.github.com>
This commit is contained in:
8157
package-lock.json
generated
8157
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -63,7 +63,7 @@
|
||||
"@commitlint/cli": "17.3.0",
|
||||
"@commitlint/config-angular": "17.3.0",
|
||||
"@edx/browserslist-config": "^1.1.1",
|
||||
"@edx/frontend-build": "12.0.6",
|
||||
"@edx/frontend-build": "12.3.0",
|
||||
"@edx/reactifex": "2.1.1",
|
||||
"codecov": "3.8.3",
|
||||
"enzyme": "3.11.0",
|
||||
|
||||
@@ -5,16 +5,14 @@ import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
function Head({ intl }) {
|
||||
return (
|
||||
<Helmet>
|
||||
<title>
|
||||
{intl.formatMessage(messages['profile.page.title'], { siteName: getConfig().SITE_NAME })}
|
||||
</title>
|
||||
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
const Head = ({ intl }) => (
|
||||
<Helmet>
|
||||
<title>
|
||||
{intl.formatMessage(messages['profile.page.title'], { siteName: getConfig().SITE_NAME })}
|
||||
</title>
|
||||
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
|
||||
</Helmet>
|
||||
);
|
||||
|
||||
Head.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
|
||||
@@ -4,35 +4,33 @@ import { Alert } from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
function AgeMessage({ accountSettingsUrl }) {
|
||||
return (
|
||||
<Alert
|
||||
variant="info"
|
||||
dismissible={false}
|
||||
show
|
||||
>
|
||||
<Alert.Heading id="profile.age.headline">
|
||||
Your profile cannot be shared.
|
||||
</Alert.Heading>
|
||||
const AgeMessage = ({ accountSettingsUrl }) => (
|
||||
<Alert
|
||||
variant="info"
|
||||
dismissible={false}
|
||||
show
|
||||
>
|
||||
<Alert.Heading id="profile.age.headline">
|
||||
Your profile cannot be shared.
|
||||
</Alert.Heading>
|
||||
<FormattedMessage
|
||||
id="profile.age.details"
|
||||
defaultMessage="To share your profile with other {siteName} learners, you must confirm that you are over the age of 13."
|
||||
description="Error message"
|
||||
tagName="p"
|
||||
values={{
|
||||
siteName: getConfig().SITE_NAME,
|
||||
}}
|
||||
/>
|
||||
<Alert.Link href={accountSettingsUrl}>
|
||||
<FormattedMessage
|
||||
id="profile.age.details"
|
||||
defaultMessage="To share your profile with other {siteName} learners, you must confirm that you are over the age of 13."
|
||||
description="Error message"
|
||||
tagName="p"
|
||||
values={{
|
||||
siteName: getConfig().SITE_NAME,
|
||||
}}
|
||||
id="profile.age.set.date"
|
||||
defaultMessage="Set your date of birth"
|
||||
description="Label on a link to set birthday"
|
||||
/>
|
||||
<Alert.Link href={accountSettingsUrl}>
|
||||
<FormattedMessage
|
||||
id="profile.age.set.date"
|
||||
defaultMessage="Set your date of birth"
|
||||
description="Label on a link to set birthday"
|
||||
/>
|
||||
</Alert.Link>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
</Alert.Link>
|
||||
</Alert>
|
||||
);
|
||||
|
||||
AgeMessage.propTypes = {
|
||||
accountSettingsUrl: PropTypes.string.isRequired,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
function Banner() {
|
||||
return <div className="profile-page-bg-banner bg-primary d-none d-md-block p-relative" />;
|
||||
}
|
||||
const Banner = () => <div className="profile-page-bg-banner bg-primary d-none d-md-block p-relative" />;
|
||||
|
||||
export default Banner;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage, FormattedDate } from '@edx/frontend-platform/i18n';
|
||||
|
||||
function DateJoined({ date }) {
|
||||
const DateJoined = ({ date }) => {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ function DateJoined({ date }) {
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
DateJoined.propTypes = {
|
||||
date: PropTypes.string,
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
export default function NotFoundPage() {
|
||||
return (
|
||||
<div className="container-fluid d-flex py-5 justify-content-center align-items-start text-center">
|
||||
<p className="my-0 py-5 text-muted" style={{ maxWidth: '32em' }}>
|
||||
<FormattedMessage
|
||||
id="profile.notfound.message"
|
||||
defaultMessage="The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again."
|
||||
description="error message when a page does not exist"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const NotFoundPage = () => (
|
||||
<div className="container-fluid d-flex py-5 justify-content-center align-items-start text-center">
|
||||
<p className="my-0 py-5 text-muted" style={{ maxWidth: '32em' }}>
|
||||
<FormattedMessage
|
||||
id="profile.notfound.message"
|
||||
defaultMessage="The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again."
|
||||
description="error message when a page does not exist"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default NotFoundPage;
|
||||
|
||||
@@ -66,21 +66,19 @@ beforeEach(() => {
|
||||
analytics.sendTrackingLogEvent.mockReset();
|
||||
});
|
||||
|
||||
function ProfilePageWrapper({
|
||||
const ProfilePageWrapper = ({
|
||||
contextValue, store, match, requiresParentalConsent,
|
||||
}) {
|
||||
return (
|
||||
<AppContext.Provider
|
||||
value={contextValue}
|
||||
>
|
||||
<IntlProvider locale="en">
|
||||
<Provider store={store}>
|
||||
<ProfilePage {...requiredProfilePageProps} match={match} requiresParentalConsent={requiresParentalConsent} />
|
||||
</Provider>
|
||||
</IntlProvider>
|
||||
</AppContext.Provider>
|
||||
);
|
||||
}
|
||||
}) => (
|
||||
<AppContext.Provider
|
||||
value={contextValue}
|
||||
>
|
||||
<IntlProvider locale="en">
|
||||
<Provider store={store}>
|
||||
<ProfilePage {...requiredProfilePageProps} match={match} requiresParentalConsent={requiresParentalConsent} />
|
||||
</Provider>
|
||||
</IntlProvider>
|
||||
</AppContext.Provider>
|
||||
);
|
||||
|
||||
ProfilePageWrapper.defaultProps = {
|
||||
match: { params: { username: 'staff' } },
|
||||
|
||||
@@ -4,22 +4,20 @@ import { VisibilityOff } from '@edx/paragon/icons';
|
||||
import { Icon } from '@edx/paragon';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
function UsernameDescription() {
|
||||
return (
|
||||
<div className="d-flex align-items-center mt-3 mb-2rem">
|
||||
<Icon src={VisibilityOff} className="icon-visibility-off" />
|
||||
<div className="username-description">
|
||||
<FormattedMessage
|
||||
id="profile.username.description"
|
||||
defaultMessage="Your profile information is only visible to you. Only your username is visible to others on {siteName}."
|
||||
description="A description of the username field"
|
||||
values={{
|
||||
siteName: getConfig().SITE_NAME,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
const UsernameDescription = () => (
|
||||
<div className="d-flex align-items-center mt-3 mb-2rem">
|
||||
<Icon src={VisibilityOff} className="icon-visibility-off" />
|
||||
<div className="username-description">
|
||||
<FormattedMessage
|
||||
id="profile.username.description"
|
||||
defaultMessage="Your profile information is only visible to you. Only your username is visible to others on {siteName}."
|
||||
description="A description of the username field"
|
||||
values={{
|
||||
siteName: getConfig().SITE_NAME,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default UsernameDescription;
|
||||
|
||||
@@ -244,14 +244,12 @@ export default connect(
|
||||
{},
|
||||
)(injectIntl(SocialLinks));
|
||||
|
||||
function SocialLink({ url, name, platform }) {
|
||||
return (
|
||||
<a href={url} className="font-weight-bold">
|
||||
<FontAwesomeIcon className="mr-2" icon={platformDisplayInfo[platform].icon} />
|
||||
{name}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
const SocialLink = ({ url, name, platform }) => (
|
||||
<a href={url} className="font-weight-bold">
|
||||
<FontAwesomeIcon className="mr-2" icon={platformDisplayInfo[platform].icon} />
|
||||
{name}
|
||||
</a>
|
||||
);
|
||||
|
||||
SocialLink.propTypes = {
|
||||
url: PropTypes.string.isRequired,
|
||||
@@ -259,9 +257,9 @@ SocialLink.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
function EditableListItem({
|
||||
const EditableListItem = ({
|
||||
url, platform, onClickEmptyContent, name,
|
||||
}) {
|
||||
}) => {
|
||||
const linkDisplay = url ? (
|
||||
<SocialLink name={name} url={url} platform={platform} />
|
||||
) : (
|
||||
@@ -269,7 +267,7 @@ function EditableListItem({
|
||||
);
|
||||
|
||||
return <li className="form-group">{linkDisplay}</li>;
|
||||
}
|
||||
};
|
||||
|
||||
EditableListItem.propTypes = {
|
||||
url: PropTypes.string,
|
||||
@@ -282,24 +280,22 @@ EditableListItem.defaultProps = {
|
||||
onClickEmptyContent: null,
|
||||
};
|
||||
|
||||
function EditingListItem({
|
||||
const EditingListItem = ({
|
||||
platform, name, value, onChange, error,
|
||||
}) {
|
||||
return (
|
||||
<li className="form-group">
|
||||
<label htmlFor={`social-${platform}`}>{name}</label>
|
||||
<input
|
||||
className={classNames('form-control', { 'is-invalid': Boolean(error) })}
|
||||
type="text"
|
||||
id={`social-${platform}`}
|
||||
name={platform}
|
||||
value={value || ''}
|
||||
onChange={onChange}
|
||||
aria-describedby="social-error-feedback"
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}) => (
|
||||
<li className="form-group">
|
||||
<label htmlFor={`social-${platform}`}>{name}</label>
|
||||
<input
|
||||
className={classNames('form-control', { 'is-invalid': Boolean(error) })}
|
||||
type="text"
|
||||
id={`social-${platform}`}
|
||||
name={platform}
|
||||
value={value || ''}
|
||||
onChange={onChange}
|
||||
aria-describedby="social-error-feedback"
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
|
||||
EditingListItem.propTypes = {
|
||||
platform: PropTypes.string.isRequired,
|
||||
@@ -314,35 +310,31 @@ EditingListItem.defaultProps = {
|
||||
error: null,
|
||||
};
|
||||
|
||||
function EmptyListItem({ onClick, name }) {
|
||||
return (
|
||||
<li className="mb-4">
|
||||
<EmptyContent onClick={onClick}>
|
||||
<FormattedMessage
|
||||
id="profile.sociallinks.add"
|
||||
defaultMessage="Add {network}"
|
||||
values={{
|
||||
network: name,
|
||||
}}
|
||||
description="{network} is the name of a social network such as Facebook or Twitter"
|
||||
/>
|
||||
</EmptyContent>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
const EmptyListItem = ({ onClick, name }) => (
|
||||
<li className="mb-4">
|
||||
<EmptyContent onClick={onClick}>
|
||||
<FormattedMessage
|
||||
id="profile.sociallinks.add"
|
||||
defaultMessage="Add {network}"
|
||||
values={{
|
||||
network: name,
|
||||
}}
|
||||
description="{network} is the name of a social network such as Facebook or Twitter"
|
||||
/>
|
||||
</EmptyContent>
|
||||
</li>
|
||||
);
|
||||
|
||||
EmptyListItem.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function StaticListItem({ name, url, platform }) {
|
||||
return (
|
||||
<li className="mb-2">
|
||||
<SocialLink name={name} url={url} platform={platform} />
|
||||
</li>
|
||||
);
|
||||
}
|
||||
const StaticListItem = ({ name, url, platform }) => (
|
||||
<li className="mb-2">
|
||||
<SocialLink name={name} url={url} platform={platform} />
|
||||
</li>
|
||||
);
|
||||
|
||||
StaticListItem.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
|
||||
@@ -47,7 +47,7 @@ configureI18n({
|
||||
messages,
|
||||
});
|
||||
|
||||
function SocialLinksWrapper(props) {
|
||||
const SocialLinksWrapper = (props) => {
|
||||
const contextValue = useMemo(() => ({
|
||||
authenticatedUser: { userId: null, username: null, administrator: false },
|
||||
config: getConfig(),
|
||||
@@ -63,7 +63,7 @@ function SocialLinksWrapper(props) {
|
||||
</IntlProvider>
|
||||
</AppContext.Provider>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SocialLinksWrapper.defaultProps = {
|
||||
store: mockStore(savingEditedBio),
|
||||
@@ -73,7 +73,7 @@ SocialLinksWrapper.propTypes = {
|
||||
store: PropTypes.shape({}),
|
||||
};
|
||||
|
||||
function SocialLinksWrapperWithStore({ store }) {
|
||||
const SocialLinksWrapperWithStore = ({ store }) => {
|
||||
const contextValue = useMemo(() => ({
|
||||
authenticatedUser: { userId: null, username: null, administrator: false },
|
||||
config: getConfig(),
|
||||
@@ -89,7 +89,7 @@ function SocialLinksWrapperWithStore({ store }) {
|
||||
</IntlProvider>
|
||||
</AppContext.Provider>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SocialLinksWrapperWithStore.defaultProps = {
|
||||
store: mockStore(savingEditedBio),
|
||||
|
||||
@@ -7,22 +7,20 @@ import { Button } from '@edx/paragon';
|
||||
|
||||
import messages from './EditButton.messages';
|
||||
|
||||
function EditButton({
|
||||
const EditButton = ({
|
||||
onClick, className, style, intl,
|
||||
}) {
|
||||
return (
|
||||
<Button
|
||||
variant="link"
|
||||
size="sm"
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
style={style}
|
||||
>
|
||||
<FontAwesomeIcon className="mr-1" icon={faPencilAlt} />
|
||||
{intl.formatMessage(messages['profile.editbutton.edit'])}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}) => (
|
||||
<Button
|
||||
variant="link"
|
||||
size="sm"
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
style={style}
|
||||
>
|
||||
<FontAwesomeIcon className="mr-1" icon={faPencilAlt} />
|
||||
{intl.formatMessage(messages['profile.editbutton.edit'])}
|
||||
</Button>
|
||||
);
|
||||
|
||||
export default injectIntl(EditButton);
|
||||
|
||||
|
||||
@@ -4,24 +4,22 @@ import PropTypes from 'prop-types';
|
||||
import EditButton from './EditButton';
|
||||
import { Visibility } from './Visibility';
|
||||
|
||||
function EditableItemHeader({
|
||||
const EditableItemHeader = ({
|
||||
content,
|
||||
showVisibility,
|
||||
visibility,
|
||||
showEditButton,
|
||||
onClickEdit,
|
||||
headingId,
|
||||
}) {
|
||||
return (
|
||||
<div className="editable-item-header mb-2">
|
||||
<h2 className="edit-section-header" id={headingId}>
|
||||
{content}
|
||||
{showEditButton ? <EditButton style={{ marginTop: '-.35rem' }} className="float-right px-0" onClick={onClickEdit} /> : null}
|
||||
</h2>
|
||||
{showVisibility ? <p className="mb-0"><Visibility to={visibility} /></p> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}) => (
|
||||
<div className="editable-item-header mb-2">
|
||||
<h2 className="edit-section-header" id={headingId}>
|
||||
{content}
|
||||
{showEditButton ? <EditButton style={{ marginTop: '-.35rem' }} className="float-right px-0" onClick={onClickEdit} /> : null}
|
||||
</h2>
|
||||
{showVisibility ? <p className="mb-0"><Visibility to={visibility} /></p> : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default EditableItemHeader;
|
||||
|
||||
|
||||
@@ -3,24 +3,22 @@ import PropTypes from 'prop-types';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
function EmptyContent({ children, onClick, showPlusIcon }) {
|
||||
return (
|
||||
<div>
|
||||
{onClick ? (
|
||||
<button
|
||||
type="button"
|
||||
className="pl-0 text-left btn btn-link"
|
||||
onClick={onClick}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') { onClick(); } }}
|
||||
tabIndex={0}
|
||||
>
|
||||
{showPlusIcon ? <FontAwesomeIcon size="xs" className="mr-2" icon={faPlus} /> : null}
|
||||
{children}
|
||||
</button>
|
||||
) : children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const EmptyContent = ({ children, onClick, showPlusIcon }) => (
|
||||
<div>
|
||||
{onClick ? (
|
||||
<button
|
||||
type="button"
|
||||
className="pl-0 text-left btn btn-link"
|
||||
onClick={onClick}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') { onClick(); } }}
|
||||
tabIndex={0}
|
||||
>
|
||||
{showPlusIcon ? <FontAwesomeIcon size="xs" className="mr-2" icon={faPlus} /> : null}
|
||||
{children}
|
||||
</button>
|
||||
) : children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default EmptyContent;
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import messages from './FormControls.messages';
|
||||
|
||||
import { VisibilitySelect } from './Visibility';
|
||||
|
||||
function FormControls({
|
||||
const FormControls = ({
|
||||
cancelHandler, changeHandler, visibility, visibilityId, saveState, intl,
|
||||
}) {
|
||||
}) => {
|
||||
// Eliminate error/failed state for save button
|
||||
const buttonState = saveState === 'error' ? null : saveState;
|
||||
|
||||
@@ -57,7 +57,7 @@ function FormControls({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default injectIntl(FormControls);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ const onChildExit = (htmlNode) => {
|
||||
}
|
||||
};
|
||||
|
||||
function SwitchContent({ expression, cases, className }) {
|
||||
const SwitchContent = ({ expression, cases, className }) => {
|
||||
const getContent = (caseKey) => {
|
||||
if (cases[caseKey]) {
|
||||
if (typeof cases[caseKey] === 'string') {
|
||||
@@ -48,7 +48,7 @@ function SwitchContent({ expression, cases, className }) {
|
||||
{getContent(expression)}
|
||||
</TransitionReplace>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SwitchContent.propTypes = {
|
||||
expression: PropTypes.string,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { faEyeSlash, faEye } from '@fortawesome/free-regular-svg-icons';
|
||||
|
||||
import messages from './Visibility.messages';
|
||||
|
||||
function Visibility({ to, intl }) {
|
||||
const Visibility = ({ to, intl }) => {
|
||||
const icon = to === 'private' ? faEyeSlash : faEye;
|
||||
const label = to === 'private'
|
||||
? intl.formatMessage(messages['profile.visibility.who.just.me'])
|
||||
@@ -18,7 +18,7 @@ function Visibility({ to, intl }) {
|
||||
<FontAwesomeIcon icon={icon} /> {label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Visibility.propTypes = {
|
||||
to: PropTypes.oneOf(['private', 'all_users']),
|
||||
@@ -30,7 +30,7 @@ Visibility.defaultProps = {
|
||||
to: 'private',
|
||||
};
|
||||
|
||||
function VisibilitySelect({ intl, className, ...props }) {
|
||||
const VisibilitySelect = ({ intl, className, ...props }) => {
|
||||
const { value } = props;
|
||||
const icon = value === 'private' ? faEyeSlash : faEye;
|
||||
|
||||
@@ -49,7 +49,7 @@ function VisibilitySelect({ intl, className, ...props }) {
|
||||
</select>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
VisibilitySelect.propTypes = {
|
||||
id: PropTypes.string,
|
||||
|
||||
Reference in New Issue
Block a user