fix(client): quick-fix for cert claiming (#42055)
* chore: reinstate the quick-fix for cert claiming
This reverts commit d80d093c8b
.
* feat: add progress to claim cert card
This commit is contained in:
committed by
GitHub
parent
5e8a64e62c
commit
7c4676d0a4
@ -506,6 +506,7 @@
|
|||||||
"certification": "{{cert}} Certification",
|
"certification": "{{cert}} Certification",
|
||||||
"browse-other": "Browse our other free certifications\n(we recommend doing these in order)",
|
"browse-other": "Browse our other free certifications\n(we recommend doing these in order)",
|
||||||
"courses": "Courses",
|
"courses": "Courses",
|
||||||
|
"steps": "Steps",
|
||||||
"expand": "Expand",
|
"expand": "Expand",
|
||||||
"collapse": "Collapse"
|
"collapse": "Collapse"
|
||||||
}
|
}
|
||||||
|
@ -554,5 +554,15 @@
|
|||||||
"Neural Network SMS Text Classifier": "Neural Network SMS Text Classifier"
|
"Neural Network SMS Text Classifier": "Neural Network SMS Text Classifier"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"certification-card": {
|
||||||
|
"title": "Claim Your Certification",
|
||||||
|
"intro": "Complete the following steps to claim and view your {{i18nCertText}}",
|
||||||
|
"complete-project": "Complete {{i18nCertText}} Projects",
|
||||||
|
"accept-honesty": "Accept our Academic Honesty Policy",
|
||||||
|
"set-name": "Set your name, and make it public",
|
||||||
|
"set-certs-public": "Set your certificication settings to public",
|
||||||
|
"set-profile-public": "Set your profile settings to public",
|
||||||
|
"set-claim": "Claim and view your certification"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,10 +260,13 @@ export class CertificationSettings extends Component {
|
|||||||
|
|
||||||
renderCertifications = certName => {
|
renderCertifications = certName => {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
const { certSlug } = first(projectMap[certName]);
|
||||||
return (
|
return (
|
||||||
<FullWidthRow key={certName}>
|
<FullWidthRow key={certName}>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<h3 className='text-center'>{certName}</h3>
|
<h3 className='text-center' id={`cert-${certSlug}`}>
|
||||||
|
{certName}
|
||||||
|
</h3>
|
||||||
<Table>
|
<Table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -448,7 +451,9 @@ export class CertificationSettings extends Component {
|
|||||||
return (
|
return (
|
||||||
<FullWidthRow key={certSlug}>
|
<FullWidthRow key={certSlug}>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<h3 className='text-center'>{certName}</h3>
|
<h3 className='text-center' id={`cert-${certSlug}`}>
|
||||||
|
{certName}
|
||||||
|
</h3>
|
||||||
<Form
|
<Form
|
||||||
buttonText={
|
buttonText={
|
||||||
fullForm ? t('buttons.claim-cert') : t('buttons.save-progress')
|
fullForm ? t('buttons.claim-cert') : t('buttons.save-progress')
|
||||||
|
@ -35,7 +35,7 @@ const Honesty = ({ isHonest, updateIsHonest }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<section className='honesty-policy'>
|
<section className='honesty-policy' id='honesty-policy'>
|
||||||
<SectionHeader>{t('settings.headings.honesty')}</SectionHeader>
|
<SectionHeader>{t('settings.headings.honesty')}</SectionHeader>
|
||||||
<FullWidthRow>
|
<FullWidthRow>
|
||||||
<Panel className='honesty-panel'>
|
<Panel className='honesty-panel'>
|
||||||
|
@ -66,7 +66,7 @@ class PrivacySettings extends Component {
|
|||||||
} = user.profileUI;
|
} = user.profileUI;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='privacy-settings'>
|
<div className='privacy-settings' id='privacy-settings'>
|
||||||
<SectionHeader>{t('settings.headings.privacy')}</SectionHeader>
|
<SectionHeader>{t('settings.headings.privacy')}</SectionHeader>
|
||||||
<FullWidthRow>
|
<FullWidthRow>
|
||||||
<p>{t('settings.privacy')}</p>
|
<p>{t('settings.privacy')}</p>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
exports[`<Honesty /> <Honesty /> snapshot when isHonest is false: Honesty 1`] = `
|
exports[`<Honesty /> <Honesty /> snapshot when isHonest is false: Honesty 1`] = `
|
||||||
<section
|
<section
|
||||||
className="honesty-policy"
|
className="honesty-policy"
|
||||||
|
id="honesty-policy"
|
||||||
>
|
>
|
||||||
<SectionHeader>
|
<SectionHeader>
|
||||||
settings.headings.honesty
|
settings.headings.honesty
|
||||||
@ -31,6 +32,7 @@ exports[`<Honesty /> <Honesty /> snapshot when isHonest is false: Honesty 1`] =
|
|||||||
exports[`<Honesty /> <Honesty /> snapshot when isHonest is true: HonestyAccepted 1`] = `
|
exports[`<Honesty /> <Honesty /> snapshot when isHonest is true: HonestyAccepted 1`] = `
|
||||||
<section
|
<section
|
||||||
className="honesty-policy"
|
className="honesty-policy"
|
||||||
|
id="honesty-policy"
|
||||||
>
|
>
|
||||||
<SectionHeader>
|
<SectionHeader>
|
||||||
settings.headings.honesty
|
settings.headings.honesty
|
||||||
|
@ -180,6 +180,7 @@ class SuperBlockIntroductionPage extends Component {
|
|||||||
{superBlock !== 'coding-interview-prep' && (
|
{superBlock !== 'coding-interview-prep' && (
|
||||||
<div>
|
<div>
|
||||||
<CertChallenge
|
<CertChallenge
|
||||||
|
isSignedIn={isSignedIn}
|
||||||
superBlock={superBlock}
|
superBlock={superBlock}
|
||||||
title={title}
|
title={title}
|
||||||
user={user}
|
user={user}
|
||||||
|
@ -15,9 +15,11 @@ import {
|
|||||||
certSlugTypeMap,
|
certSlugTypeMap,
|
||||||
superBlockCertTypeMap
|
superBlockCertTypeMap
|
||||||
} from '../../../../../config/certification-settings';
|
} from '../../../../../config/certification-settings';
|
||||||
|
import CertificationCard from './CertificationCard';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
currentCerts: CurrentCertsType,
|
currentCerts: CurrentCertsType,
|
||||||
|
isSignedIn: PropTypes.bool.isRequired,
|
||||||
superBlock: PropTypes.string,
|
superBlock: PropTypes.string,
|
||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
@ -36,6 +38,7 @@ const mapStateToProps = (state, props) => {
|
|||||||
export class CertChallenge extends Component {
|
export class CertChallenge extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
isSignedIn,
|
||||||
superBlock,
|
superBlock,
|
||||||
t,
|
t,
|
||||||
title,
|
title,
|
||||||
@ -54,9 +57,17 @@ export class CertChallenge extends Component {
|
|||||||
const i18nCertText = t(`intro:misc-text.certification`, {
|
const i18nCertText = t(`intro:misc-text.certification`, {
|
||||||
cert: i18nSuperBlock
|
cert: i18nSuperBlock
|
||||||
});
|
});
|
||||||
|
const { certSlug } = cert;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='block'>
|
<div className='block'>
|
||||||
|
{isSignedIn && !isCertified && (
|
||||||
|
<CertificationCard
|
||||||
|
certSlug={certSlug}
|
||||||
|
i18nCertText={i18nCertText}
|
||||||
|
superBlock={superBlock}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
className={`map-cert-title ${
|
className={`map-cert-title ${
|
||||||
isCertified ? 'map-is-cert' : 'no-cursor'
|
isCertified ? 'map-is-cert' : 'no-cursor'
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import ScrollableAnchor from 'react-scrollable-anchor';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import ClaimCertSteps from './ClaimCertSteps';
|
||||||
|
import Caret from '../../../assets/icons/Caret';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
certSlug: PropTypes.string,
|
||||||
|
i18nCertText: PropTypes.string,
|
||||||
|
superBlock: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
const CertificationCard = ({ certSlug, superBlock, i18nCertText }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [isExpanded, setIsExpanded] = useState(true);
|
||||||
|
|
||||||
|
const handleBlockClick = () => {
|
||||||
|
setIsExpanded(!isExpanded);
|
||||||
|
};
|
||||||
|
|
||||||
|
const { expand: expandText, collapse: collapseText, steps: stepsText } = t(
|
||||||
|
'intro:misc-text'
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<ScrollableAnchor id='claim-cert-block'>
|
||||||
|
<div className={`block ${isExpanded ? 'open' : ''}`}>
|
||||||
|
<div className='block-title-wrapper'>
|
||||||
|
<a className='block-link' href='#claim-cert-block'>
|
||||||
|
<h3 className='big-block-title'>
|
||||||
|
{t('certification-card.title')}
|
||||||
|
<span className='block-link-icon'>#</span>
|
||||||
|
</h3>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className='block-description'>
|
||||||
|
{t('certification-card.intro', { i18nCertText })}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
aria-expanded={isExpanded}
|
||||||
|
className='map-title'
|
||||||
|
onClick={handleBlockClick}
|
||||||
|
>
|
||||||
|
<Caret />
|
||||||
|
<h4 className='course-title'>
|
||||||
|
{`${
|
||||||
|
isExpanded ? collapseText : expandText
|
||||||
|
} ${stepsText.toLowerCase()}`}
|
||||||
|
</h4>
|
||||||
|
</button>
|
||||||
|
{isExpanded && (
|
||||||
|
<ClaimCertSteps
|
||||||
|
certSlug={certSlug}
|
||||||
|
i18nCertText={i18nCertText}
|
||||||
|
superBlock={superBlock}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ScrollableAnchor>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CertificationCard.displayName = 'CertStatus';
|
||||||
|
CertificationCard.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default CertificationCard;
|
@ -0,0 +1,99 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Link } from 'gatsby';
|
||||||
|
import { withTranslation, useTranslation } from 'react-i18next';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
|
import GreenPass from '../../../assets/icons/GreenPass';
|
||||||
|
import GreenNotCompleted from '../../../assets/icons/GreenNotCompleted';
|
||||||
|
import { userSelector } from '../../../redux';
|
||||||
|
import { User } from '../../../redux/propTypes';
|
||||||
|
|
||||||
|
const mapIconStyle = { height: '15px', marginRight: '10px', width: '15px' };
|
||||||
|
const renderCheckMark = isCompleted => {
|
||||||
|
return isCompleted ? (
|
||||||
|
<GreenPass style={mapIconStyle} />
|
||||||
|
) : (
|
||||||
|
<GreenNotCompleted style={mapIconStyle} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
certSlug: PropTypes.string,
|
||||||
|
i18nCertText: PropTypes.string,
|
||||||
|
superBlock: PropTypes.string,
|
||||||
|
user: User
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return createSelector(userSelector, user => ({
|
||||||
|
user
|
||||||
|
}))(state);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ClaimCertSteps = ({ certSlug, i18nCertText, superBlock, user }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const settingsLink = '/settings#privacy-settings';
|
||||||
|
const certClaimLink = `/settings#cert-${certSlug}`;
|
||||||
|
const honestyPolicyAnchor = '/settings#honesty-policy';
|
||||||
|
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
isHonest,
|
||||||
|
profileUI: { isLocked, showCerts, showName }
|
||||||
|
} = user;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className='map-challenges-ul'>
|
||||||
|
<li className='map-challenge-title map-project-wrap'>
|
||||||
|
<Link to={honestyPolicyAnchor}>
|
||||||
|
{t('certification-card.accept-honesty')}
|
||||||
|
<span className='badge map-badge map-project-checkmark'>
|
||||||
|
{renderCheckMark(isHonest)}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className='map-challenge-title map-project-wrap'>
|
||||||
|
<Link to={settingsLink}>
|
||||||
|
{t('certification-card.set-profile-public')}
|
||||||
|
<span className='badge map-badge map-project-checkmark'>
|
||||||
|
{renderCheckMark(!isLocked)}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className='map-challenge-title map-project-wrap'>
|
||||||
|
<Link to={settingsLink}>
|
||||||
|
{t('certification-card.set-certs-public')}
|
||||||
|
<span className='badge map-badge map-project-checkmark'>
|
||||||
|
{renderCheckMark(showCerts)}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className='map-challenge-title map-project-wrap'>
|
||||||
|
<Link to={settingsLink}>
|
||||||
|
{t('certification-card.set-name')}
|
||||||
|
<span className='badge map-badge map-project-checkmark'>
|
||||||
|
{renderCheckMark(name && name !== '' && showName)}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className='map-challenge-title map-project-wrap'>
|
||||||
|
<a href={`#${superBlock}-projects`}>
|
||||||
|
{t('certification-card.complete-project', {
|
||||||
|
i18nCertText
|
||||||
|
})}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li className='map-challenge-title map-project-wrap'>
|
||||||
|
<Link to={certClaimLink}>{t('certification-card.set-claim')}</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ClaimCertSteps.displayName = 'ClaimCertSteps';
|
||||||
|
ClaimCertSteps.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(withTranslation()(ClaimCertSteps));
|
Reference in New Issue
Block a user