From 845659105f1883aeaf6840b1d8b522107d4a80fe Mon Sep 17 00:00:00 2001 From: Ismail Tlemcani <34961373+Ismailtlem@users.noreply.github.com> Date: Tue, 30 Nov 2021 19:36:33 +0100 Subject: [PATCH] feat(client): ts-migration for Introduction templates (#43752) * chore: rename the file CertificationCard.js to tsx * refactor: refactor the file CertificationCard to tsx refactor: refactor the file CertificationCard to tsx refactor: refactor the file CertificationCard to tsx * chore: rename the file ClaimCertSteps.js to tsx * refactor: refactor the file ClaimCertSteps to TS * chore: rename the file SuperBlockIntro.js to tsx * refactor: refactor the file SuperBlockIntro to TS * chore: rename the file Block.js to tsx * refactor: refactor the file Block to TS refactor: refactor the file Block to TS refactor: refactor the file Block to TS * chore: rename the file CertChallenge.js to tsx * refactor: refactor the file CertChallenge to TS * fix typing * ignore missing redux store connection Co-authored-by: ismail Co-authored-by: Ismail Tlemcani Co-authored-by: Shaun Hamilton --- client/src/redux/prop-types.ts | 16 ++-- .../components/{Block.js => block.tsx} | 87 +++++++++++-------- .../{CertChallenge.js => cert-challenge.tsx} | 86 +++++++++--------- ...ficationCard.js => certification-card.tsx} | 35 ++++---- ...ClaimCertSteps.js => claim-cert-steps.tsx} | 21 +++-- ...perBlockIntro.js => super-block-intro.tsx} | 18 ++-- .../Introduction/super-block-intro.tsx | 6 +- client/src/utils/ajax.ts | 19 +++- 8 files changed, 164 insertions(+), 124 deletions(-) rename client/src/templates/Introduction/components/{Block.js => block.tsx} (76%) rename client/src/templates/Introduction/components/{CertChallenge.js => cert-challenge.tsx} (73%) rename client/src/templates/Introduction/components/{CertificationCard.js => certification-card.tsx} (82%) rename client/src/templates/Introduction/components/{ClaimCertSteps.js => claim-cert-steps.tsx} (87%) rename client/src/templates/Introduction/components/{SuperBlockIntro.js => super-block-intro.tsx} (73%) diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts index b48238930b..cf5f8fdf56 100644 --- a/client/src/redux/prop-types.ts +++ b/client/src/redux/prop-types.ts @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import { HandlerProps } from 'react-reflex'; import { SuperBlocks } from '../../../config/certification-settings'; +import { certMap } from '../resources/cert-and-project-map'; export const UserPropType = PropTypes.shape({ about: PropTypes.string, @@ -63,12 +64,13 @@ export const CurrentCertsPropType = PropTypes.arrayOf( }) ); -export const StepsPropType = PropTypes.shape({ - currentCerts: CurrentCertsPropType, - isShowCerts: PropTypes.bool, - isShowName: PropTypes.bool, - isShowProfile: PropTypes.bool -}); +export type Steps = { + isHonest?: boolean; + currentCerts?: Array; + isShowCerts?: boolean; + isShowName?: boolean; + isShowProfile?: boolean; +}; export type CurrentCert = { show: boolean; @@ -83,7 +85,7 @@ export type MarkdownRemark = { block: string; isBeta: boolean; superBlock: SuperBlocks; - title: string; + title: typeof certMap[number]['title']; }; headings: [ { diff --git a/client/src/templates/Introduction/components/Block.js b/client/src/templates/Introduction/components/block.tsx similarity index 76% rename from client/src/templates/Introduction/components/Block.js rename to client/src/templates/Introduction/components/block.tsx index c36df06a63..6ac690dafd 100644 --- a/client/src/templates/Introduction/components/Block.js +++ b/client/src/templates/Introduction/components/block.tsx @@ -1,9 +1,8 @@ -import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import { withTranslation } from 'react-i18next'; +import { withTranslation, TFunction } from 'react-i18next'; import { connect } from 'react-redux'; import ScrollableAnchor from 'react-scrollable-anchor'; -import { bindActionCreators } from 'redux'; +import { bindActionCreators, Dispatch } from 'redux'; import { createSelector } from 'reselect'; import store from 'store'; @@ -12,60 +11,69 @@ import { isAuditedCert } from '../../../../../utils/is-audited'; import Caret from '../../../assets/icons/caret'; import GreenNotCompleted from '../../../assets/icons/green-not-completed'; import GreenPass from '../../../assets/icons/green-pass'; -import { Link } from '../../../components/helpers/'; +import { Link } from '../../../components/helpers'; import { completedChallengesSelector, executeGA } from '../../../redux'; +import { ChallengeNode, CompletedChallenge } from '../../../redux/prop-types'; import { makeExpandedBlockSelector, toggleBlock } from '../redux'; import Challenges from './Challenges'; const { curriculumLocale } = envData; -const mapStateToProps = (state, ownProps) => { +const mapStateToProps = ( + state: unknown, + ownProps: { blockDashedName: string } & unknown +) => { const expandedSelector = makeExpandedBlockSelector(ownProps.blockDashedName); return createSelector( expandedSelector, completedChallengesSelector, - (isExpanded, completedChallenges) => ({ + (isExpanded: boolean, completedChallenges: CompletedChallenge[]) => ({ isExpanded, - completedChallenges: completedChallenges.map(({ id }) => id) + completedChallengeIds: completedChallenges.map(({ id }) => id) }) )(state); }; -const mapDispatchToProps = dispatch => +const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators({ toggleBlock, executeGA }, dispatch); -const propTypes = { - blockDashedName: PropTypes.string, - challenges: PropTypes.array, - completedChallenges: PropTypes.arrayOf(PropTypes.string), - executeGA: PropTypes.func, - isExpanded: PropTypes.bool, - superBlock: PropTypes.string, - t: PropTypes.func, - toggleBlock: PropTypes.func.isRequired -}; +interface BlockProps { + blockDashedName: string; + challenges: ChallengeNode[]; + completedChallengeIds: string[]; + executeGA: typeof executeGA; + isExpanded: boolean; + superBlock: string; + t: TFunction; + toggleBlock: typeof toggleBlock; +} const mapIconStyle = { height: '15px', marginRight: '10px', width: '15px' }; -export class Block extends Component { - constructor(...props) { - super(...props); +export class Block extends Component { + static displayName: string; + constructor(props: BlockProps) { + super(props); this.handleBlockClick = this.handleBlockClick.bind(this); } - handleBlockClick() { + handleBlockClick(): void { const { blockDashedName, toggleBlock, executeGA } = this.props; - const playSound = store.get('fcc-sound'); + const playSound = store.get('fcc-sound') as boolean; if (playSound) { - void import('tone').then(tone => { + void (async () => { + const tone = await import('tone'); + const player = new tone.Player( 'https://tonejs.github.io/audio/berklee/guitar_chord1.mp3' ).toDestination(); - if (tone.context.state !== 'running') tone.context.resume(); + if (tone.context.state !== 'running') { + void tone.context.resume(); + } player.autostart = playSound; - }); + })(); } executeGA({ type: 'event', @@ -74,10 +82,10 @@ export class Block extends Component { action: blockDashedName } }); - return toggleBlock(blockDashedName); + toggleBlock(blockDashedName); } - renderCheckMark(isCompleted) { + renderCheckMark(isCompleted: boolean): JSX.Element { return isCompleted ? ( ) : ( @@ -85,7 +93,7 @@ export class Block extends Component { ); } - renderBlockIntros(arr) { + renderBlockIntros(arr: string[]): JSX.Element { return (
{arr.map((str, i) => ( @@ -95,10 +103,10 @@ export class Block extends Component { ); } - render() { + render(): JSX.Element { const { blockDashedName, - completedChallenges, + completedChallengeIds, challenges, isExpanded, superBlock, @@ -108,8 +116,8 @@ export class Block extends Component { let completedCount = 0; const challengesWithCompleted = challenges.map(challenge => { const { id } = challenge; - const isCompleted = completedChallenges.some( - completedId => id === completedId + const isCompleted = completedChallengeIds.some( + (completedChallengeId: string) => completedChallengeId === id ); if (isCompleted) { completedCount++; @@ -134,13 +142,19 @@ export class Block extends Component { ); }); - const blockIntroObj = t(`intro:${superBlock}.blocks.${blockDashedName}`); + const blockIntroObj: { title?: string; intro: string[] } = t( + `intro:${superBlock}.blocks.${blockDashedName}` + ); const blockTitle = blockIntroObj ? blockIntroObj.title : null; const blockIntroArr = blockIntroObj ? blockIntroObj.intro : []; const { expand: expandText, collapse: collapseText, courses: coursesText + }: { + expand: string; + collapse: string; + courses: string; } = t('intro:misc-text'); return isProjectBlock ? ( @@ -196,7 +210,9 @@ export class Block extends Component {