Fix: Settings/Portfolio UI (#17202)

* chore(names): Certificate -> Certification

* fix(style): Profile Certs alignment and font-size

* fix(button): Remove user icon

* fix(style): Adjust profile timeline UI

* fix(style): General account settings style fixes

* chore(updateEmail): Remove update email until we sort out auth0

* fix(copy): website -> personal website

* fix(copy): profile -> portfolio

* feat(home): Add legacy certs to user home page

* fix(copy): Change Honest settings copy

* fix(cert-settings): Filter out 'take home's

* fix(copy): next lesson -> next coding challenge

* fix(alignment): Align portfolio item settings' buttons
This commit is contained in:
Stuart Taylor
2018-05-21 16:21:15 +01:00
committed by Quincy Larson
parent 848e04028e
commit a76c8aff5a
33 changed files with 259 additions and 134 deletions

View File

@ -121,7 +121,9 @@ export function projectsSelector(state) {
);
return Object.keys(blocks)
.filter(key =>
key.includes('projects') && !key.includes('coding-interview')
key.includes('projects') && !(
key.includes('coding-interview') || key.includes('take-home')
)
)
.map(key => blocks[key])
.concat(legacyWithDashedNames)

View File

@ -58,7 +58,7 @@ function CamperHOC({
location={ showLocation && location }
name={ showName && name }
picture={ picture }
points={ showPoints && points }
points={ showPoints ? points : 0 }
username={ username }
/>
<hr />

View File

@ -9,6 +9,8 @@ import {
Col
} from 'react-bootstrap';
import { FullWidthRow } from '../../../helperComponents';
import { userByNameSelector } from '../../../redux';
const mapStateToProps = createSelector(
@ -40,59 +42,59 @@ const mapStateToProps = createSelector(
currentCerts: [
{
show: is2018FullStackCert,
title: 'Full Stack Certificate:',
title: 'Full Stack Certification:',
showURL: '2018-full-stack'
},
{
show: isRespWebDesignCert,
title: 'Responsive Web Design Certificate:',
title: 'Responsive Web Design Certification:',
showURL: 'responsive-web-design'
},
{
show: isJsAlgoDataStructCert,
title: 'JavaScript Algorithms and Data Structures Certificate:',
title: 'JavaScript Algorithms and Data Structures Certification:',
showURL: 'javascript-algorithms-and-data-structures'
},
{
show: isFrontEndLibsCert,
title: 'Front End Libraries Certificate:',
title: 'Front End Libraries Certification:',
showURL: 'front-end-libraries'
},
{
show: is2018DataVisCert,
title: 'Data Visualization Certificate:',
title: 'Data Visualization Certification:',
showURL: 'data-visualization'
},
{
show: isApisMicroservicesCert,
title: 'APIs and Microservices Certificate:',
title: 'APIs and Microservices Certification:',
showURL: 'apis-and-microservices'
},
{
show: isInfosecQaCert,
title: 'Information Security and Quality Assurance Certificate:',
title: 'Information Security and Quality Assurance Certification:',
showURL: 'information-security-and-quality-assurance'
}
],
legacyCerts: [
{
show: isFullStackCert,
title: 'Full Stack Certificate:',
title: 'Full Stack Certification:',
showURL: 'legacy-full-stack'
},
{
show: isFrontEndCert,
title: 'Front End Certificate:',
title: 'Front End Certification:',
showURL: 'legacy-front-end'
},
{
show: isBackEndCert,
title: 'Back End Certificate:',
title: 'Back End Certification:',
showURL: 'legacy-back-end'
},
{
show: isDataVisCert,
title: 'Data Visualization Certificate:',
title: 'Data Visualization Certification:',
showURL: 'legacy-data-visualization'
}
]
@ -123,7 +125,7 @@ function renderCertShow(username, cert) {
return cert.show ? (
<Row key={ cert.showURL }>
<Col sm={ 8 }>
<p>
<p className='bigger-text'>
<strong>
{ cert.title }
</strong>
@ -134,7 +136,7 @@ function renderCertShow(username, cert) {
block={ true }
bsSize='lg'
bsStyle='primary'
href={ `/certificates/${username}/${cert.showURL}`}
href={ `/certification/${username}/${cert.showURL}`}
>
Show
</Button>
@ -154,25 +156,27 @@ function Certificates({
const renderCertShowWithUsername = _.curry(renderCertShow)(username);
return (
<div>
<h2 className='text-center'>freeCodeCamp Certificates</h2>
<br />
{
hasModernCert ?
currentCerts.map(renderCertShowWithUsername) :
<p className='text-center' >
No certificates have been earned under the current curriculum
</p>
}
{
hasLegacyCert ?
<div>
<h3>Legacy Certifications</h3>
{
legacyCerts.map(renderCertShowWithUsername)
}
</div> :
null
}
<FullWidthRow>
<h2 className='text-center'>freeCodeCamp Certifications</h2>
<br />
{
hasModernCert ?
currentCerts.map(renderCertShowWithUsername) :
<p className='text-center' >
No certifications have been earned under the current curriculum
</p>
}
{
hasLegacyCert ?
<div>
<h3>Legacy Certifications</h3>
{
legacyCerts.map(renderCertShowWithUsername)
}
</div> :
null
}
</FullWidthRow>
<hr />
</div>
);

View File

@ -3,8 +3,10 @@ import PropTypes from 'prop-types';
import { createSelector } from 'reselect';
import { connect } from 'react-redux';
import format from 'date-fns/format';
import { reverse, sortBy } from 'lodash';
import { find, reverse, sortBy } from 'lodash';
import {
Button,
Modal,
Table
} from 'react-bootstrap';
@ -12,18 +14,20 @@ import { challengeIdToNameMapSelector } from '../../../entities';
import { userByNameSelector } from '../../../redux';
import { homeURL } from '../../../../utils/constantStrings.json';
import blockNameify from '../../../utils/blockNameify';
import { FullWidthRow } from '../../../helperComponents';
import { Link } from '../../../Router';
import { FullWidthRow } from '../../../helperComponents';
import SolutionViewer from '../../Settings/components/SolutionViewer.jsx';
const mapStateToProps = createSelector(
challengeIdToNameMapSelector,
userByNameSelector,
(
idToNameMap,
{ completedChallenges: completedMap = [] }
{ completedChallenges: completedMap = [], username }
) => ({
completedMap,
idToNameMap
idToNameMap,
username
})
);
@ -32,38 +36,94 @@ const propTypes = {
PropTypes.shape({
id: PropTypes.string,
completedDate: PropTypes.number,
challengeType: PropTypes.number
challengeType: PropTypes.number,
solution: PropTypes.string,
files: PropTypes.shape({
ext: PropTypes.string,
contents: PropTypes.string
})
})
),
idToNameMap: PropTypes.objectOf(PropTypes.string)
idToNameMap: PropTypes.objectOf(PropTypes.string),
username: PropTypes.string
};
class Timeline extends PureComponent {
constructor(props) {
super(props);
this.state = {
solutionToView: null,
solutionOpen: false
};
this.closeSolution = this.closeSolution.bind(this);
this.renderCompletion = this.renderCompletion.bind(this);
this.viewSolution = this.viewSolution.bind(this);
}
renderCompletion(completed) {
const { idToNameMap } = this.props;
const { id, completedDate } = completed;
const { id, completedDate, solution, files } = completed;
const challengeDashedName = idToNameMap[id];
return (
<tr key={ id }>
<td>{ blockNameify(idToNameMap[id]) }</td>
<td>
<a href={`/challenges/${challengeDashedName}`}>
{ blockNameify(challengeDashedName) }
</a>
</td>
<td className='text-center'>
<time dateTime={ format(completedDate, 'YYYY-MM-DDTHH:MM:SSZ') }>
{
format(completedDate, 'MMMM DD YYYY')
format(completedDate, 'MMMM D, YYYY')
}
</time>
</td>
<td>
{/* eslint-disable no-nested-ternary */
files ? (
<Button
block={ true }
bsStyle='primary'
onClick={ () => this.viewSolution(id) }
>
View&nbsp;Solution
</Button>
) : solution ? (
<Button
block={ true }
bsStyle='primary'
href={solution}
target='_blank'
>
View&nbsp;Solution
</Button>
) : ''
}
</td>
</tr>
);
}
viewSolution(id) {
this.setState(state => ({
...state,
solutionToView: id,
solutionOpen: true
}));
}
closeSolution() {
this.setState(state => ({
...state,
solutionToView: null,
solutionOpen: false
}));
}
render() {
const { completedMap, idToNameMap } = this.props;
const { completedMap, idToNameMap, username } = this.props;
const { solutionToView: id, solutionOpen } = this.state;
if (!Object.keys(idToNameMap).length) {
return null;
}
@ -82,7 +142,7 @@ class Timeline extends PureComponent {
<thead>
<tr>
<th>Challenge</th>
<th>First Completed</th>
<th className='text-center'>First Completed</th>
</tr>
</thead>
<tbody>
@ -98,6 +158,30 @@ class Timeline extends PureComponent {
</tbody>
</Table>
}
{
id &&
<Modal
aria-labelledby='contained-modal-title'
onHide={this.closeSolution}
show={ solutionOpen }
>
<Modal.Header closeButton={ true }>
<Modal.Title id='contained-modal-title'>
{ `${username}'s Solution to ${blockNameify(idToNameMap[id])}` }
</Modal.Title>
</Modal.Header>
<Modal.Body>
<SolutionViewer
solution={
find(completedMap, ({id: completedId}) => completedId === id)
}
/>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.closeSolution}>Close</Button>
</Modal.Footer>
</Modal>
}
</FullWidthRow>
);
}

View File

@ -13,6 +13,18 @@
background-color: #fff;
}
.bigger-text {
font-size: 1.7rem;
}
.bio {
text-align: center;
}
.name, .location, .bio, .points {
font-size: 2rem;
margin-bottom: 0;
}
.@{ns}-container {
@ -41,10 +53,6 @@
}
}
.bio {
text-align: center;
}
h2, h3 {
&.name, &.username, &.points, &.location {
margin-top: 0;

View File

@ -4,7 +4,6 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Button } from 'react-bootstrap';
import FA from 'react-fontawesome';
import ns from './ns.json';
import { FullWidthRow, Spacer, Loader } from '../../helperComponents';
@ -85,8 +84,7 @@ export class Settings extends React.Component {
bsStyle='primary'
className='btn-link-social'
>
<FA name='user' />
Show me my public profile
Show me my public portfolio
</Button>
</Link>
<Button

View File

@ -12,7 +12,6 @@ import { FullWidthRow, Spacer } from '../../../helperComponents';
import ThemeSettings from './ThemeSettings.jsx';
import Camper from './Camper.jsx';
import UsernameSettings from './UsernameSettings.jsx';
import SectionHeader from './SectionHeader.jsx';
import { userSelector, toggleNightMode } from '../../../redux';
import { updateUserBackend } from '../redux';
import {
@ -165,9 +164,6 @@ class AboutSettings extends PureComponent {
const toggleTheme = () => toggleNightMode(username, currentTheme);
return (
<div className='about-settings'>
<SectionHeader>
About Settings
</SectionHeader>
<UsernameSettings username={ username }/>
<FullWidthRow>
<Nav

View File

@ -180,7 +180,7 @@ class CertificationSettings extends PureComponent {
<FullWidthRow key={superBlock}>
<h3 className='project-heading'>{ projectBlockName }</h3>
<Form
buttonText={ fullForm ? 'Claim Certificate' : 'Save Progress' }
buttonText={ fullForm ? 'Claim Certification' : 'Save Progress' }
enableSubmit={ fullForm }
formFields={ challengeTitles.concat([ 'id' ]) }
hideButton={isCertClaimed}
@ -198,10 +198,10 @@ class CertificationSettings extends PureComponent {
block={ true }
bsSize='lg'
bsStyle='primary'
href={ `/certificates/${username}/${superBlock}`}
href={ `/certification/${username}/${superBlock}`}
target='_blank'
>
Show Certificate
Show Certification
</Button> :
null
}
@ -215,11 +215,11 @@ class CertificationSettings extends PureComponent {
const { allProjects } = this.props;
let project = _.find(allProjects, { superBlock: id });
if (!project) {
// the submitted projects do not belong to current/legacy certificates
// the submitted projects do not belong to current/legacy certifications
return this.props.createError(
new Error(
'Submitted projects do not belong to either current or ' +
'legacy certificates'
'legacy certifications'
)
);
}
@ -268,7 +268,7 @@ class CertificationSettings extends PureComponent {
<FullWidthRow>
<p>
Add links to the live demos of your projects as you finish them.
Then, once you have added all 5 projects required for a certificate,
Then, once you have added all 5 projects required for a certification,
you can claim it.
</p>
</FullWidthRow>
@ -276,7 +276,7 @@ class CertificationSettings extends PureComponent {
modernProjects.map(this.buildProjectForms)
}
<SectionHeader>
Legacy Certificate Settings
Legacy Certification Settings
</SectionHeader>
{
legacyProjects.map(this.buildProjectForms)

View File

@ -13,13 +13,29 @@ import {
} from 'react-bootstrap';
import TB from '../Toggle-Button';
import EmailForm from './EmailForm.jsx';
// import EmailForm from './EmailForm.jsx';
import { Link } from '../../../Router';
import { FullWidthRow, Spacer } from '../../../helperComponents';
import { FullWidthRow } from '../../../helperComponents';
import SectionHeader from './SectionHeader.jsx';
import { userSelector } from '../../../redux';
import { onRouteUpdateEmail, updateMyEmail, updateUserBackend } from '../redux';
/**
Removed functionality until we can update auth0 at the same time
<FullWidthRow>
<UpdateEmailButton />
</FullWidthRow>
<FullWidthRow>
<EmailForm
initialValues={{ email, confrimEmail: ''}}
/>
</FullWidthRow>
<Spacer />
*/
const mapStateToProps = createSelector(
userSelector,
({
@ -101,9 +117,8 @@ class EmailSettings extends PureComponent {
You do not have an email associated with this account.
</p>
</FullWidthRow>
<FullWidthRow>
<UpdateEmailButton />
</FullWidthRow>
</div>
);
}
@ -124,12 +139,8 @@ class EmailSettings extends PureComponent {
</HelpBlock>
</FullWidthRow>
}
<FullWidthRow>
<EmailForm
initialValues={{ email, confrimEmail: ''}}
/>
</FullWidthRow>
<Spacer />
<FullWidthRow>
<Row className='inline-form-field' key='sendQuincyEmail'>
<Col sm={ 8 }>

View File

@ -45,7 +45,7 @@ class Honesty extends PureComponent {
const isHonestAgreed = (
<Panel bsStyle='info'>
<p>
You have already accepted our Academic Honesty Policy
You have accepted our Academic Honesty Policy
</p>
</Panel>
);

View File

@ -22,12 +22,17 @@ const mapStateToProps = createSelector(
githubProfile,
linkedin,
twitter,
website
personalWebsite: website
}
})
);
const formFields = [ 'githubProfile', 'linkedin', 'twitter', 'website' ];
const formFields = [
'githubProfile',
'linkedin',
'twitter',
'personalWebsite'
];
function mapDispatchToProps(dispatch) {
return bindActionCreators({
@ -40,10 +45,10 @@ const propTypes = {
githubProfile: PropTypes.string,
handleSubmit: PropTypes.func.isRequired,
linkedin: PropTypes.string,
personalWebsite: PropTypes.string,
twitter: PropTypes.string,
updateUserBackend: PropTypes.func.isRequired,
username: PropTypes.string,
website: PropTypes.string
username: PropTypes.string
};
class InternetSettings extends PureComponent {
@ -53,8 +58,8 @@ class InternetSettings extends PureComponent {
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(values) {
this.props.updateUserBackend(values);
handleSubmit({personalWebsite, ...others}) {
this.props.updateUserBackend({ ...others, website: personalWebsite });
}
render() {

View File

@ -43,7 +43,7 @@ class JSAlgoAndDSForm extends PureComponent {
e.preventDefault();
const { username, superBlock, isCertClaimed } = this.props;
if (isCertClaimed) {
return this.props.hardGoTo(`/certificates/${username}/${superBlock}`);
return this.props.hardGoTo(`/certification/${username}/${superBlock}`);
}
return this.props.claimCert(superBlock);
}
@ -107,7 +107,7 @@ class JSAlgoAndDSForm extends PureComponent {
Object.keys(jsProjects).length === completeCount ?
<form onSubmit={ this.handleSubmit }>
<BlockSaveButton>
{ isCertClaimed ? 'Show' : 'Claim'} Certificate
{ isCertClaimed ? 'Show' : 'Claim'} Certification
</BlockSaveButton>
</form> :
null

View File

@ -26,7 +26,7 @@ function ResetModal(props) {
<Modal.Body>
<p>
This will really delete all of your progress, points, completed
challenges, our records of your projects, any certificates you have,
challenges, our records of your projects, any certifications you have,
everything.
</p>
<p>

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { reduxForm } from 'redux-form';
import { FormFields, BlockSaveButton, BlockSaveWrapper } from './';
import { FormFields, BlockSaveButton } from './';
const propTypes = {
buttonText: PropTypes.string,
@ -50,22 +50,20 @@ function DynamicForm({
fields={ fields }
options={ options }
/>
<BlockSaveWrapper>
{
hideButton ?
null :
<BlockSaveButton
disabled={
allPristine && !enableSubmit ||
(!!Object.keys(errors).filter(key => errors[key]).length)
}
>
{
buttonText ? buttonText : null
}
</BlockSaveButton>
}
</BlockSaveWrapper>
{
hideButton ?
null :
<BlockSaveButton
disabled={
allPristine && !enableSubmit ||
(!!Object.keys(errors).filter(key => errors[key]).length)
}
>
{
buttonText ? buttonText : null
}
</BlockSaveButton>
}
</form>
);
}

View File

@ -1,5 +1,5 @@
const policy = [
'Before you can claim a verified certificate, you must accept the ' +
'Before you can claim a verified certification, you must accept the ' +
'Academic Honesty Policy below.',
'I understand that plagiarism means copying someone elses work and ' +
'presenting the work as if it were my own, without clearly attributing ' +

View File

@ -138,7 +138,7 @@ function sendCertifiedEmail(
from: 'team@freeCodeCamp.org',
subject: dedent`
Congratulations on completing all of the
freeCodeCamp certificates!
freeCodeCamp certifications!
`,
text: renderCertifedEmail({
username,
@ -190,16 +190,16 @@ export default function certificate(app) {
verifyCert
);
router.get(
'/certificates/:username/:cert',
'/certification/:username/:cert',
showCert
);
app.use(router);
const noNameMessage = dedent`
We need your name so we can put it on your certificate.
We need your name so we can put it on your certification.
Add your name to your account settings and click the save button.
Then we can issue your certificate.
Then we can issue your certification.
`;
const notCertifiedMessage = name => dedent`

View File

@ -39,11 +39,12 @@ module.exports = function(app, done) {
const homePage = user ? 'userHome' : 'noUserHome';
const { quote, author} = getRandomQuote();
const title = user ?
`Welcome back ${user.name ? user.name : 'Camper'}` :
`Welcome, ${user.name ? user.name : 'Camper'}!` :
'Learn to Code and Help Nonprofits';
const completedChallengeCount = user && user.completedChallengeCount || 0;
const completedProjectCount = user && user.completedProjectCount || 0;
const completedCertCount = user && user.completedCertCount || 0;
const completedLegacyCertCount = user && user.completedLegacyCertCount || 0;
Promise.all([
// news.getFeed(),
About.getActiveUsersForRendering()
@ -60,6 +61,7 @@ module.exports = function(app, done) {
completedChallengeCount,
completedProjectCount,
completedCertCount,
completedLegacyCertCount,
// feed,
quote,
title

View File

@ -22,7 +22,14 @@ function getCompletedCertCount(user) {
'isJsAlgoDataStructCert',
'isRespWebDesignCert'
].reduce((sum, key) => user[key] ? sum + 1 : sum, 0);
}
function getLegacyCertCount(user) {
return [
'isFrontEndCert',
'isBackEndCert',
'isDataVisCert'
].reduce((sum, key) => user[key] ? sum + 1 : sum, 0);
}
PassportConfigurator.prototype.init = function passportInit(noSession) {
@ -72,6 +79,7 @@ PassportConfigurator.prototype.init = function passportInit(noSession) {
user.completedChallengeCount = completedChallengeCount;
user.completedProjectCount = completedProjectCount;
user.completedCertCount = getCompletedCertCount(user);
user.completedLegacyCertCount = getLegacyCertCount(user);
user.completedChallenges = [];
return done(null, user);
});

View File

@ -20,7 +20,7 @@ include styles
h3 has successfully completed freeCodeCamp's
h1
strong Advanced Frontend Projects
h4 1 of 3 legacy freeCodeCamp certificates, representing approximately 400 hours of coursework
h4 1 of 3 legacy freeCodeCamp certification, representing approximately 400 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/advanced-front-end
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/advanced-front-end

View File

@ -20,7 +20,7 @@ include styles
h3 has successfully completed freeCodeCamp's
h1
strong APIs and Microservices Projects
h4 1 of 6 freeCodeCamp certificates, representing approximately 300 hours of coursework
h4 1 of 6 freeCodeCamp certifications, representing approximately 300 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/apis-and-microservices
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/apis-and-microservices

View File

@ -20,7 +20,7 @@ include styles
h3 has successfully completed freeCodeCamp's
h1
strong Data Visualization Projects
h4 1 of 6 freeCodeCamp certificates, representing approximately 300 hours of coursework
h4 1 of 6 freeCodeCamp certifications, representing approximately 300 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/data-visualization
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/data-visualization

View File

@ -20,7 +20,7 @@ include styles
h3 has successfully completed freeCodeCamp's
h1
strong Front End Libraries Projects
h4 1 of 6 freeCodeCamp certificates, representing approximately 300 hours of coursework
h4 1 of 6 freeCodeCamp certifications, representing approximately 300 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/front-end-libraries
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/front-end-libraries

View File

@ -20,7 +20,7 @@ include styles
h3 has successfully completed freeCodeCamp's
h1
strong Information Security and Quality Assurance Projects
h4 1 of 6 freeCodeCamp certificates, representing approximately 300 hours of coursework
h4 1 of 6 freeCodeCamp certifications, representing approximately 300 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/information-security-and-quality-assurance
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/information-security-and-quality-assurance

View File

@ -19,8 +19,8 @@ include styles
strong= name
h3 has successfully completed freeCodeCamp's
h1
strong JavaScript Algorithms and Data Structures Certificate
h4 1 of 6 freeCodeCamp certificates, representing approximately 300 hours of coursework
strong JavaScript Algorithms and Data Structures Projects
h4 1 of 6 freeCodeCamp certifications, representing approximately 300 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/javascript-algorithms-and-data-structures
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/javascript-algorithms-and-data-structures

View File

@ -20,7 +20,7 @@ include ../styles
h3 has successfully completed freeCodeCamp's
h1
strong Back End Development Projects
h4 1 of 3 legacy freeCodeCamp certificates, representing approximately 400 hours of coursework
h4 1 of 3 legacy freeCodeCamp certifications, representing approximately 400 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include ../styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/legacy-back-end
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/legacy-back-end

View File

@ -20,7 +20,7 @@ include ../styles
h3 has successfully completed freeCodeCamp's
h1
strong Data Visualization Projects
h4 1 of 3 legacy freeCodeCamp certificates, representing approximately 400 hours of coursework
h4 1 of 3 legacy freeCodeCamp certifications, representing approximately 400 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include ../styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/legacy-data-visualization
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/legacy-data-visualization

View File

@ -20,7 +20,7 @@ include ../styles
h3 has successfully completed freeCodeCamp's
h1
strong Front End Development Projects
h4 1 of 3 legacy freeCodeCamp certificates, representing approximately 400 hours of coursework
h4 1 of 3 legacy freeCodeCamp certifications, representing approximately 400 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include ../styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/legacy-front-end
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/legacy-front-end

View File

@ -20,7 +20,7 @@ include ../styles
h3 has successfully completed freeCodeCamp's
h1
strong Legacy Full Stack Development Program
h4 All three of the legacy freeCodeCamp certificates, representing approximately 12000 hours of coursework
h4 All three of the legacy freeCodeCamp certifications, representing approximately 12000 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include ../styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/legacy-full-stack
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/legacy-full-stack

View File

@ -20,7 +20,7 @@ include styles
h3 has successfully completed freeCodeCamp's
h1
strong Responsive Web Design Projects
h4 1 of 6 freeCodeCamp certificates, representing approximately 300 hours of coursework
h4 1 of 6 freeCodeCamp certifications, representing approximately 300 hours of coursework
footer
.row.signatures
@ -29,4 +29,4 @@ include styles
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certificate at: https://freecodecamp.org/certificates/#{username}/responsive-web-design
p.verify Verify this certification at: https://freecodecamp.org/certification/#{username}/responsive-web-design

View File

@ -1,8 +1,8 @@
Hi <%= name || username %>,
Congratulations on completing all of the freeCodeCamp certificates!
Congratulations on completing all of the freeCodeCamp certifications!
All of your certificates are now live at at: https://www.freecodecamp.org/<%= username %>
All of your certifications are now live at at: https://www.freecodecamp.org/<%= username %>
Please tell me a bit more about you and your near-term goals.

View File

@ -16,6 +16,15 @@
strong
span.green-text 30
| projects
if !!completedLegacyCertCount
p.stats
| You have earned&nbsp;
strong
span.green-text=completedLegacyCertCount
| out of&nbsp;
strong
span.green-text 3
| legacy certifications
p.stats
| You have earned&nbsp;
strong

View File

@ -13,7 +13,7 @@ block content
.col-xs-12.col-sm-12.col-md-4
img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landing-icon-certificate.svg', alt='Help nonprofits with bro bono code projects')
p.large-p Build projects and earn free certificates.
p.large-p Build projects and earn free certifications.
.col-xs-12.col-sm-12.col-md-4
img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landing-icon-experience.svg', alt='Get hired as a developer and start your software engineer career')

View File

@ -15,7 +15,7 @@ block content
.big-break
.row
.col-xs-12.col-sm-8.col-sm-offset-2
a.btn.btn-cta.btn-block.btn-lg.btn-primary(href="/challenges/current-challenge") Go to my next lesson
a.btn.btn-cta.btn-block.btn-lg.btn-primary(href="/challenges/current-challenge") Go to my next coding challenge
.big-break
.big-break
.big-break