fix(description): Adjust for new description format
This commit is contained in:
@ -26,13 +26,6 @@ export default function settingsController(app) {
|
||||
createValidatorErrorHandler(alertTypes.danger),
|
||||
updateMyCurrentChallenge
|
||||
);
|
||||
api.post(
|
||||
'/update-my-current-challenge',
|
||||
ifNoUser401,
|
||||
updateMyCurrentChallengeValidators,
|
||||
createValidatorErrorHandler(alertTypes.danger),
|
||||
updateMyCurrentChallenge
|
||||
);
|
||||
api.post('/update-my-portfolio', ifNoUser401, updateMyPortfolio);
|
||||
api.post('/update-my-projects', ifNoUser401, updateMyProjects);
|
||||
api.post(
|
||||
|
@ -1,10 +1,11 @@
|
||||
import helmet from 'helmet';
|
||||
|
||||
import { homeLocation } from '../../../config/env';
|
||||
|
||||
let trusted = [
|
||||
"'self'",
|
||||
'https://search.freecodecamp.org',
|
||||
'https://www.freecodecamp.rocks',
|
||||
'https://api.freecodecamp.rocks',
|
||||
homeLocation,
|
||||
'https://' + process.env.AUTH0_DOMAIN
|
||||
];
|
||||
|
||||
@ -12,9 +13,7 @@ const host = process.env.HOST || 'localhost';
|
||||
const port = process.env.SYNC_PORT || '3000';
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
trusted = trusted.concat([
|
||||
`ws://${host}:${port}`
|
||||
]);
|
||||
trusted = trusted.concat([`ws://${host}:${port}`, 'http://localhost:8000']);
|
||||
}
|
||||
|
||||
export default function csp() {
|
||||
@ -73,11 +72,9 @@ export default function csp() {
|
||||
'*',
|
||||
'data:'
|
||||
],
|
||||
mediaSrc: [
|
||||
'*.bitly.com',
|
||||
'*.amazonaws.com',
|
||||
'*.twitter.com'
|
||||
].concat(trusted),
|
||||
mediaSrc: ['*.bitly.com', '*.amazonaws.com', '*.twitter.com'].concat(
|
||||
trusted
|
||||
),
|
||||
frameSrc: [
|
||||
'*.gitter.im',
|
||||
'*.gitter.im https:',
|
||||
|
@ -22,7 +22,7 @@ export const ChallengeNode = PropTypes.shape({
|
||||
block: PropTypes.string,
|
||||
challengeType: PropTypes.number,
|
||||
dashedName: PropTypes.string,
|
||||
description: PropTypes.arrayOf(PropTypes.string),
|
||||
description: PropTypes.string,
|
||||
files: PropTypes.shape({
|
||||
indexhtml: FileType,
|
||||
indexjs: FileType
|
||||
@ -34,6 +34,7 @@ export const ChallengeNode = PropTypes.shape({
|
||||
guideUrl: PropTypes.string,
|
||||
head: PropTypes.arrayOf(PropTypes.string),
|
||||
challengeOrder: PropTypes.number,
|
||||
instructions: PropTypes.string,
|
||||
isBeta: PropTypes.bool,
|
||||
isComingSoon: PropTypes.bool,
|
||||
isLocked: PropTypes.bool,
|
||||
|
@ -41,7 +41,7 @@ const reduxFormPropTypes = {
|
||||
};
|
||||
|
||||
const propTypes = {
|
||||
description: PropTypes.arrayOf(PropTypes.string),
|
||||
description: PropTypes.string,
|
||||
executeChallenge: PropTypes.func.isRequired,
|
||||
id: PropTypes.string,
|
||||
output: PropTypes.string,
|
||||
@ -126,7 +126,8 @@ export class BackEnd extends Component {
|
||||
challengeNode: {
|
||||
fields: { blockName, slug },
|
||||
title,
|
||||
description
|
||||
description,
|
||||
instructions
|
||||
}
|
||||
},
|
||||
output,
|
||||
@ -145,7 +146,10 @@ export class BackEnd extends Component {
|
||||
<Spacer />
|
||||
<div>
|
||||
<ChallengeTitle>{blockNameTitle}</ChallengeTitle>
|
||||
<ChallengeDescription description={description} />
|
||||
<ChallengeDescription
|
||||
description={description}
|
||||
instructions={instructions}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Form
|
||||
@ -200,6 +204,7 @@ export const query = graphql`
|
||||
title
|
||||
guideUrl
|
||||
description
|
||||
instructions
|
||||
challengeType
|
||||
fields {
|
||||
blockName
|
||||
|
@ -177,6 +177,7 @@ class ShowClassic extends Component {
|
||||
fields: { blockName, slug },
|
||||
title,
|
||||
description,
|
||||
instructions,
|
||||
videoUrl
|
||||
}
|
||||
},
|
||||
@ -227,6 +228,7 @@ class ShowClassic extends Component {
|
||||
className='full-height'
|
||||
description={description}
|
||||
guideUrl={createGuideUrl(slug)}
|
||||
instructions={instructions}
|
||||
section={dasherize(blockName)}
|
||||
title={blockNameTitle}
|
||||
videoUrl={videoUrl}
|
||||
@ -271,6 +273,7 @@ export const query = graphql`
|
||||
challengeNode(fields: { slug: { eq: $slug } }) {
|
||||
title
|
||||
description
|
||||
instructions
|
||||
challengeType
|
||||
videoUrl
|
||||
fields {
|
||||
|
@ -1,44 +1,29 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Col, Row } from '@freecodecamp/react-bootstrap';
|
||||
import { descriptionRegex } from '../../../../utils';
|
||||
|
||||
import './challenge-description.css';
|
||||
|
||||
const propTypes = {
|
||||
description: PropTypes.arrayOf(PropTypes.string),
|
||||
description: PropTypes.string,
|
||||
instructions: PropTypes.string,
|
||||
section: PropTypes.string
|
||||
};
|
||||
|
||||
function renderDescription(description) {
|
||||
if (!Array.isArray(description)) {
|
||||
return null;
|
||||
}
|
||||
return description.map((line, index) => {
|
||||
if (descriptionRegex.test(line)) {
|
||||
return (
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: line }}
|
||||
key={line.slice(-6) + index}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<p
|
||||
className='wrappable'
|
||||
dangerouslySetInnerHTML={{ __html: line }}
|
||||
key={line.slice(-6) + index}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function ChallengeDescription({ description, section }) {
|
||||
// TODO: Remove bootstrap
|
||||
function ChallengeDescription({ description, instructions, section }) {
|
||||
return (
|
||||
<Row>
|
||||
<Col className={`challenge-instructions ${section}`} xs={12}>
|
||||
{renderDescription(description)}
|
||||
<div dangerouslySetInnerHTML={{ __html: description }} />
|
||||
{instructions ? (
|
||||
<Fragment>
|
||||
<hr />
|
||||
<div dangerouslySetInnerHTML={{ __html: instructions }} />
|
||||
<hr />
|
||||
</Fragment>
|
||||
) : (
|
||||
<hr />
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ReactDom from 'react-dom';
|
||||
import { connect } from 'react-redux';
|
||||
@ -29,16 +29,17 @@ const mapDispatchToProps = dispatch =>
|
||||
const MathJax = global.MathJax;
|
||||
|
||||
const propTypes = {
|
||||
description: PropTypes.arrayOf(PropTypes.string),
|
||||
description: PropTypes.string,
|
||||
guideUrl: PropTypes.string,
|
||||
initConsole: PropTypes.func.isRequired,
|
||||
instructions: PropTypes.string,
|
||||
section: PropTypes.string,
|
||||
tests: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string,
|
||||
videoUrl: PropTypes.string
|
||||
};
|
||||
|
||||
export class SidePanel extends PureComponent {
|
||||
export class SidePanel extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.bindTopDiv = this.bindTopDiv.bind(this);
|
||||
@ -84,6 +85,7 @@ export class SidePanel extends PureComponent {
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
instructions,
|
||||
guideUrl,
|
||||
tests,
|
||||
section,
|
||||
@ -95,7 +97,7 @@ export class SidePanel extends PureComponent {
|
||||
<Spacer />
|
||||
<div>
|
||||
<ChallengeTitle>{title}</ChallengeTitle>
|
||||
<ChallengeDescription description={description} section={section} />
|
||||
<ChallengeDescription description={description} instructions={instructions} section={section} />
|
||||
</div>
|
||||
<ToolPanel guideUrl={guideUrl} videoUrl={videoUrl} />
|
||||
<TestSuite tests={tests} />
|
||||
|
@ -1,37 +1,24 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ChallengeTitle from '../components/Challenge-Title';
|
||||
import Spacer from '../../../components/helpers/Spacer';
|
||||
|
||||
const propTypes = {
|
||||
description: PropTypes.arrayOf(PropTypes.string),
|
||||
description: PropTypes.string,
|
||||
isCompleted: PropTypes.bool,
|
||||
isSignedIn: PropTypes.bool,
|
||||
title: PropTypes.string
|
||||
};
|
||||
|
||||
export default class SidePanel extends PureComponent {
|
||||
renderDescription(title = '', description = []) {
|
||||
return description.map((line, index) => (
|
||||
<li
|
||||
className='step-text wrappable'
|
||||
dangerouslySetInnerHTML={{ __html: line }}
|
||||
key={title.slice(6) + index}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { title, description, isCompleted } = this.props;
|
||||
export default function SidePanel({ title, description, isCompleted }) {
|
||||
return (
|
||||
<div>
|
||||
<Spacer />
|
||||
<ChallengeTitle isCompleted={isCompleted}>{title}</ChallengeTitle>
|
||||
<ul>{this.renderDescription(title, description)}</ul>
|
||||
<div dangerouslySetInnerHTML={{ __html: description }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SidePanel.displayName = 'ProjectSidePanel';
|
||||
SidePanel.propTypes = propTypes;
|
||||
|
@ -39,7 +39,6 @@ class GuideArticle extends Component {
|
||||
},
|
||||
pageContext: { meta }
|
||||
} = this.props;
|
||||
console.log(title);
|
||||
return (
|
||||
<Layout>
|
||||
<Helmet>
|
||||
|
Reference in New Issue
Block a user