feat(client): ts-migrate client/src/components/helpers/** (#42593)
* refactor(client): convert toggle-button to TypeScript
* chore: rename Space to tsx
* refactor(client): convert space to TypeScript
* chore: rename SlimWidthRow to tsx
* refactor(client): slim-width-row to TypeScript
* chore: rename SkeletonSprite to ts
* fix: fixed typos and resolved paths
* chore: resolve path inconsistencies
* refactor(client): skelton-sprite to TypeScript
* chore: rename loader.test to tsx
* chore: add types for react-spinkit
* refactor(client): loader to TypeScript
* refactor(client): link to TypeScript
* refactor(client): image-loader to TypeScript
* refactor(client): full-width-row to TypeScript
* refactor(client): current-challenge-link to TypeScript
* refactor(client): button to TypeScript
* refactor(client): border-color-picker to TypeScript
* refactor(client): avatar-renderer to TypeScript
* chore: changed loadertest(snap) to ts
* chore: optional types added and cleaned files
* fix: args are now optional
* push small updates for Spacer component merge
* update snapshot
* remove type defs from deps
* Revert "remove type defs from deps"
This reverts commit 9f58bf3554
.
* correctly remove client type deps
* final push to remove from deps
Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
committed by
Mrugesh Mohapatra
parent
660c3b3440
commit
4b44bb37d9
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
|
||||
import Loader from '../components/helpers/Loader';
|
||||
import Loader from '../components/helpers/loader';
|
||||
import {
|
||||
userByNameSelector,
|
||||
userProfileFetchStateSelector,
|
||||
|
@ -5,7 +5,7 @@ import Helmet from 'react-helmet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import envData from '../../../config/env.json';
|
||||
import FullWidthRow from '../components/helpers/FullWidthRow';
|
||||
import FullWidthRow from '../components/helpers/full-width-row';
|
||||
import { Spacer } from '../components/helpers';
|
||||
|
||||
const { apiLocation } = envData;
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
defaultDonation,
|
||||
modalDefaultDonation
|
||||
} from '../../../../config/donation-settings';
|
||||
import Spacer from '../helpers/Spacer';
|
||||
import Spacer from '../helpers/spacer';
|
||||
import PaypalButton from './PaypalButton';
|
||||
import DonateCompletion from './DonateCompletion';
|
||||
import {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Link from '../helpers/Link';
|
||||
import Link from '../helpers/link';
|
||||
import './footer.css';
|
||||
|
||||
const propTypes = {
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link, Spacer, Loader, FullWidthRow } from '../helpers';
|
||||
import { randomQuote } from '../../utils/get-words';
|
||||
import CurrentChallengeLink from '../helpers/CurrentChallengeLink';
|
||||
import CurrentChallengeLink from '../helpers/current-challenge-link';
|
||||
import IntroDescription from './components/IntroDescription';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const styles = { padding: '15px 0', height: '1px' };
|
||||
|
||||
const Comp = props => <div className='spacer' style={styles} {...props} />;
|
||||
|
||||
const Spacer = ({ size = 1 }) =>
|
||||
size === 1 ? (
|
||||
<Comp />
|
||||
) : (
|
||||
'#'
|
||||
.repeat(size)
|
||||
.split('')
|
||||
.map((_, i) => <Comp key={`spacer_${i}`} />)
|
||||
);
|
||||
|
||||
Spacer.propTypes = {
|
||||
size: PropTypes.number
|
||||
};
|
||||
|
||||
export default Spacer;
|
@ -1,22 +1,26 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Image } from '@freecodecamp/react-bootstrap';
|
||||
import DefaultAvatar from '../../assets/icons/DefaultAvatar';
|
||||
import { defaultUserImage } from '../../../../config/misc';
|
||||
import { borderColorPicker } from '../helpers';
|
||||
import { borderColorPicker } from '.';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
isDonating: PropTypes.bool,
|
||||
isTopContributor: PropTypes.bool,
|
||||
picture: PropTypes.any.isRequired,
|
||||
userName: PropTypes.string.isRequired
|
||||
};
|
||||
interface AvatarRendererProps {
|
||||
isDonating?: boolean;
|
||||
isTopContributor?: boolean;
|
||||
picture: string;
|
||||
userName: string;
|
||||
}
|
||||
|
||||
function AvatarRenderer({ picture, userName, isDonating, isTopContributor }) {
|
||||
function AvatarRenderer({
|
||||
picture,
|
||||
userName,
|
||||
isDonating,
|
||||
isTopContributor
|
||||
}: AvatarRendererProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
let borderColor = borderColorPicker(isDonating, isTopContributor);
|
||||
let isPlaceHolderImage =
|
||||
const borderColor: string = borderColorPicker(isDonating, isTopContributor);
|
||||
const isPlaceHolderImage =
|
||||
/example.com|identicon.org/.test(picture) || picture === defaultUserImage;
|
||||
|
||||
return (
|
||||
@ -35,6 +39,5 @@ function AvatarRenderer({ picture, userName, isDonating, isTopContributor }) {
|
||||
);
|
||||
}
|
||||
|
||||
AvatarRenderer.propTypes = propTypes;
|
||||
AvatarRenderer.displayName = 'AvatarRenderer';
|
||||
export default AvatarRenderer;
|
@ -1,4 +1,7 @@
|
||||
export default function borderColorPicker(isDonating, isTopContributor) {
|
||||
export default function borderColorPicker(
|
||||
isDonating?: boolean,
|
||||
isTopContributor?: boolean
|
||||
): string {
|
||||
if (isDonating && isTopContributor) return 'purple-border';
|
||||
else if (isTopContributor) return 'blue-border';
|
||||
else if (isDonating) return 'gold-border';
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
function ButtonSpacer() {
|
||||
function ButtonSpacer(): JSX.Element {
|
||||
return <div className='button-spacer' style={{ padding: '5px 0' }} />;
|
||||
}
|
||||
|
@ -1,18 +1,22 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import envData from '../../../../config/env.json';
|
||||
|
||||
const { apiLocation } = envData;
|
||||
interface EnvData {
|
||||
apiLocation: string;
|
||||
}
|
||||
|
||||
const { apiLocation } = envData as EnvData;
|
||||
|
||||
const currentChallengeApi = '/challenges/current-challenge';
|
||||
|
||||
const propTypes = {
|
||||
children: PropTypes.any,
|
||||
isLargeBtn: PropTypes.bool
|
||||
};
|
||||
|
||||
function CurrentChallengeLink({ children, isLargeBtn }) {
|
||||
function CurrentChallengeLink({
|
||||
children,
|
||||
isLargeBtn
|
||||
}: {
|
||||
children?: JSX.ElementChildrenAttribute;
|
||||
isLargeBtn?: boolean;
|
||||
}): JSX.Element {
|
||||
let classNames;
|
||||
if (isLargeBtn) {
|
||||
classNames = 'btn btn-lg btn-primary btn-block';
|
||||
@ -27,6 +31,5 @@ function CurrentChallengeLink({ children, isLargeBtn }) {
|
||||
}
|
||||
|
||||
CurrentChallengeLink.displayName = 'CurrentChallengeLink';
|
||||
CurrentChallengeLink.propTypes = propTypes;
|
||||
|
||||
export default CurrentChallengeLink;
|
@ -1,8 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Row, Col } from '@freecodecamp/react-bootstrap';
|
||||
|
||||
function FullWidthRow({ children, className }) {
|
||||
function FullWidthRow({
|
||||
children,
|
||||
className
|
||||
}: {
|
||||
children?: JSX.ElementChildrenAttribute;
|
||||
className?: string;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<Row className={className}>
|
||||
<Col sm={8} smOffset={2} xs={12}>
|
||||
@ -13,9 +18,5 @@ function FullWidthRow({ children, className }) {
|
||||
}
|
||||
|
||||
FullWidthRow.displayName = 'FullWidthRow';
|
||||
FullWidthRow.propTypes = {
|
||||
children: PropTypes.any,
|
||||
className: PropTypes.string
|
||||
};
|
||||
|
||||
export default FullWidthRow;
|
@ -1,20 +1,21 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import './image-loader.css';
|
||||
// @ts-ignore
|
||||
import LazyLoad from 'react-lazy-load';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const propTypes = {
|
||||
alt: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
height: PropTypes.number,
|
||||
loadedClassName: PropTypes.string,
|
||||
loadingClassName: PropTypes.string,
|
||||
offsetVertical: PropTypes.number,
|
||||
src: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
width: PropTypes.number
|
||||
};
|
||||
interface ImageLoaderProps {
|
||||
alt?: string;
|
||||
className?: string;
|
||||
height?: number;
|
||||
loadedClassName?: string;
|
||||
loadingClassName?: string;
|
||||
offsetVertical?: number;
|
||||
src?: string;
|
||||
style?: React.CSSProperties;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
const ImageLoader = ({
|
||||
className = '',
|
||||
@ -26,7 +27,7 @@ const ImageLoader = ({
|
||||
style,
|
||||
width,
|
||||
height
|
||||
}) => {
|
||||
}: ImageLoaderProps): JSX.Element => {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const fullClassName = `${className} ${
|
||||
loaded ? loadedClassName : loadingClassName
|
||||
@ -49,5 +50,5 @@ const ImageLoader = ({
|
||||
</LazyLoad>
|
||||
);
|
||||
};
|
||||
ImageLoader.propTypes = propTypes;
|
||||
|
||||
export default ImageLoader;
|
@ -1,11 +1,11 @@
|
||||
export { default as ButtonSpacer } from './ButtonSpacer';
|
||||
export { default as FullWidthRow } from './FullWidthRow';
|
||||
export { default as SlimWidthRow } from './SlimWidthRow';
|
||||
export { default as Loader } from './Loader';
|
||||
export { default as SkeletonSprite } from './SkeletonSprite';
|
||||
export { default as Spacer } from './Spacer';
|
||||
export { default as Link } from './Link';
|
||||
export { default as CurrentChallengeLink } from './CurrentChallengeLink';
|
||||
export { default as ImageLoader } from './ImageLoader';
|
||||
export { default as AvatarRenderer } from './AvatarRenderer';
|
||||
export { default as borderColorPicker } from './borderColorPicker';
|
||||
export { default as ButtonSpacer } from './button-spacer';
|
||||
export { default as FullWidthRow } from './full-width-row';
|
||||
export { default as SlimWidthRow } from './slim-width-row';
|
||||
export { default as Loader } from './loader';
|
||||
export { default as SkeletonSprite } from './skeleton-sprite';
|
||||
export { default as Spacer } from './spacer';
|
||||
export { default as Link } from './link';
|
||||
export { default as CurrentChallengeLink } from './current-challenge-link';
|
||||
export { default as ImageLoader } from './image-loader';
|
||||
export { default as AvatarRenderer } from './avatar-renderer';
|
||||
export { default as borderColorPicker } from './border-color-picker';
|
||||
|
@ -1,13 +1,15 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import renderer, { ReactTestRendererJSON } from 'react-test-renderer';
|
||||
|
||||
import Link from './Link';
|
||||
import Link from './link';
|
||||
|
||||
describe('<Link />', () => {
|
||||
const externalLink = renderer
|
||||
.create(<Link external={true} to='/home' />)
|
||||
.toJSON();
|
||||
const gatsbyLink = renderer.create(<Link to='/home' />).toJSON();
|
||||
.toJSON() as ReactTestRendererJSON;
|
||||
const gatsbyLink = renderer
|
||||
.create(<Link to='/home' />)
|
||||
.toJSON() as ReactTestRendererJSON;
|
||||
|
||||
it('renders to the DOM', () => {
|
||||
expect(gatsbyLink).toBeTruthy();
|
@ -1,15 +1,20 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link as GatsbyLink } from 'gatsby';
|
||||
|
||||
const propTypes = {
|
||||
children: PropTypes.any,
|
||||
external: PropTypes.bool,
|
||||
sameTab: PropTypes.bool,
|
||||
to: PropTypes.string.isRequired
|
||||
};
|
||||
interface LinkProps {
|
||||
children?: JSX.ElementChildrenAttribute;
|
||||
external?: boolean;
|
||||
sameTab?: boolean;
|
||||
to: string;
|
||||
}
|
||||
|
||||
const Link = ({ children, to, external, sameTab, ...other }) => {
|
||||
const Link = ({
|
||||
children,
|
||||
to,
|
||||
external,
|
||||
sameTab,
|
||||
...other
|
||||
}: LinkProps): JSX.Element => {
|
||||
if (!external && /^\/(?!\/)/.test(to)) {
|
||||
return (
|
||||
<GatsbyLink to={to} {...other}>
|
||||
@ -30,6 +35,5 @@ const Link = ({ children, to, external, sameTab, ...other }) => {
|
||||
</a>
|
||||
);
|
||||
};
|
||||
Link.propTypes = propTypes;
|
||||
|
||||
export default Link;
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { render, cleanup } from '@testing-library/react';
|
||||
|
||||
import Loader from './Loader';
|
||||
import Loader from './loader';
|
||||
|
||||
describe('<Loader />', () => {
|
||||
afterEach(cleanup);
|
@ -1,13 +1,16 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Spinner from 'react-spinkit';
|
||||
|
||||
import './loader.css';
|
||||
|
||||
function Loader({ fullScreen, timeout }) {
|
||||
interface LoaderProps {
|
||||
fullScreen?: boolean;
|
||||
timeout?: number;
|
||||
}
|
||||
function Loader({ fullScreen, timeout }: LoaderProps): JSX.Element {
|
||||
const [showSpinner, setShowSpinner] = useState(!timeout);
|
||||
useEffect(() => {
|
||||
let timerId;
|
||||
let timerId: ReturnType<typeof setTimeout>;
|
||||
if (!showSpinner) {
|
||||
timerId = setTimeout(() => setShowSpinner(true), timeout);
|
||||
}
|
||||
@ -21,9 +24,5 @@ function Loader({ fullScreen, timeout }) {
|
||||
}
|
||||
|
||||
Loader.displayName = 'Loader';
|
||||
Loader.propTypes = {
|
||||
fullScreen: PropTypes.bool,
|
||||
timeout: PropTypes.number
|
||||
};
|
||||
|
||||
export default Loader;
|
@ -1,8 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
import styles from './skeletonStyles';
|
||||
import styles from './skeleton-styles';
|
||||
|
||||
function SkeletonSprite() {
|
||||
// TODO: unsure about parameter typing
|
||||
function SkeletonSprite({}: React.FC<
|
||||
React.ComponentPropsWithoutRef<'svg'>
|
||||
>): JSX.Element {
|
||||
return (
|
||||
<div className='sprite-container'>
|
||||
<style dangerouslySetInnerHTML={{ __html: styles }} />
|
@ -1,8 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Row, Col } from '@freecodecamp/react-bootstrap';
|
||||
|
||||
function SlimWidthRow({ children, ...restProps }) {
|
||||
interface SlimWidthRowProps {
|
||||
children: JSX.ElementChildrenAttribute;
|
||||
}
|
||||
function SlimWidthRow({
|
||||
children,
|
||||
...restProps
|
||||
}: SlimWidthRowProps): JSX.Element {
|
||||
return (
|
||||
<Row {...restProps}>
|
||||
<Col md={6} mdOffset={3} sm={12}>
|
||||
@ -13,8 +18,5 @@ function SlimWidthRow({ children, ...restProps }) {
|
||||
}
|
||||
|
||||
SlimWidthRow.displayName = 'SlimWidthRow';
|
||||
SlimWidthRow.propTypes = {
|
||||
children: PropTypes.any
|
||||
};
|
||||
|
||||
export default SlimWidthRow;
|
24
client/src/components/helpers/spacer.tsx
Normal file
24
client/src/components/helpers/spacer.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
|
||||
interface SpacerProps {
|
||||
size: number;
|
||||
}
|
||||
|
||||
const styles = { padding: '15px 0', height: '1px' };
|
||||
|
||||
const Comp = ({ ...props }): JSX.Element => (
|
||||
<div className='spacer' style={styles} {...props} />
|
||||
);
|
||||
|
||||
const Spacer = ({ size = 1 }: SpacerProps): JSX.Element =>
|
||||
size === 1 ? (
|
||||
<Comp />
|
||||
) : (
|
||||
<>
|
||||
{Array.from(Array(size), (_, i) => (
|
||||
<Comp key={`spacer_${i}`} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
||||
export default Spacer;
|
@ -1,5 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
ToggleButtonGroup as BSBG,
|
||||
ToggleButton as TB
|
||||
@ -9,15 +8,18 @@ import './toggle-button.css';
|
||||
import ToggleCheck from '../../assets/icons/ToggleCheck';
|
||||
import Spacer from '../../assets/icons/Spacer';
|
||||
|
||||
const propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
offLabel: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onLabel: PropTypes.string,
|
||||
value: PropTypes.bool.isRequired
|
||||
};
|
||||
interface ButtonProps {
|
||||
name: string;
|
||||
offLabel: string;
|
||||
onChange: (value: string) => void;
|
||||
onLabel: string;
|
||||
value: boolean;
|
||||
condition: boolean;
|
||||
}
|
||||
|
||||
function getActiveClass(condition) {
|
||||
type ActiveClass = Pick<ButtonProps, 'condition'>;
|
||||
|
||||
function getActiveClass(condition: ActiveClass | unknown) {
|
||||
return condition ? 'active' : 'not-active';
|
||||
}
|
||||
|
||||
@ -27,7 +29,7 @@ export default function ToggleButton({
|
||||
value,
|
||||
onLabel = 'On',
|
||||
offLabel = 'Off'
|
||||
}) {
|
||||
}: ButtonProps): JSX.Element {
|
||||
const checkIconStyle = {
|
||||
height: '15px',
|
||||
width: '20px'
|
||||
@ -71,4 +73,3 @@ export default function ToggleButton({
|
||||
}
|
||||
|
||||
ToggleButton.displayName = 'ToggleButton';
|
||||
ToggleButton.propTypes = propTypes;
|
@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Grid, Row } from '@freecodecamp/react-bootstrap';
|
||||
import Helmet from 'react-helmet';
|
||||
import Link from '../helpers/Link';
|
||||
import Link from '../helpers/link';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { CurrentChallengeLink, FullWidthRow, Spacer } from '../helpers';
|
||||
|
@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { AvatarRenderer } from '../../helpers';
|
||||
import SocialIcons from './SocialIcons';
|
||||
import Link from '../../helpers/Link';
|
||||
import Link from '../../helpers/link';
|
||||
|
||||
import './camper.css';
|
||||
|
||||
|
@ -9,8 +9,8 @@ import startOfDay from 'date-fns/startOfDay';
|
||||
import isEqual from 'date-fns/isEqual';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import FullWidthRow from '../../helpers/FullWidthRow';
|
||||
import Spacer from '../../helpers/Spacer';
|
||||
import FullWidthRow from '../../helpers/full-width-row';
|
||||
import Spacer from '../../helpers/spacer';
|
||||
|
||||
import '@freecodecamp/react-calendar-heatmap/dist/styles.css';
|
||||
import './heatmap.css';
|
||||
|
@ -17,8 +17,8 @@ import { Trans, withTranslation } from 'react-i18next';
|
||||
import { updateMyEmail } from '../../redux/settings';
|
||||
import { maybeEmailRE } from '../../utils';
|
||||
|
||||
import FullWidthRow from '../helpers/FullWidthRow';
|
||||
import Spacer from '../helpers/Spacer';
|
||||
import FullWidthRow from '../helpers/full-width-row';
|
||||
import Spacer from '../helpers/spacer';
|
||||
import SectionHeader from './SectionHeader';
|
||||
import BlockSaveButton from '../helpers/form/BlockSaveButton';
|
||||
import ToggleSetting from './ToggleSetting';
|
||||
|
@ -9,8 +9,8 @@ import { withTranslation } from 'react-i18next';
|
||||
import { userSelector } from '../../redux';
|
||||
import { submitProfileUI } from '../../redux/settings';
|
||||
|
||||
import FullWidthRow from '../helpers/FullWidthRow';
|
||||
import Spacer from '../helpers/Spacer';
|
||||
import FullWidthRow from '../helpers/full-width-row';
|
||||
import Spacer from '../helpers/spacer';
|
||||
import ToggleSetting from './ToggleSetting';
|
||||
import SectionHeader from './SectionHeader';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import FullWidthRow from '../helpers/FullWidthRow';
|
||||
import FullWidthRow from '../helpers/full-width-row';
|
||||
|
||||
const propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
HelpBlock
|
||||
} from '@freecodecamp/react-bootstrap';
|
||||
|
||||
import TB from '../helpers/ToggleButton';
|
||||
import TB from '../helpers/toggle-button';
|
||||
import { ButtonSpacer } from '../helpers';
|
||||
|
||||
import './toggle-setting.css';
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
submitNewUsername
|
||||
} from '../../redux/settings';
|
||||
import BlockSaveButton from '../helpers/form/BlockSaveButton';
|
||||
import FullWidthRow from '../helpers/FullWidthRow';
|
||||
import FullWidthRow from '../helpers/full-width-row';
|
||||
import { isValidUsername } from '../../../../utils/validate';
|
||||
|
||||
const propTypes = {
|
||||
|
@ -29,7 +29,7 @@ import CompletionModal from '../../components/CompletionModal';
|
||||
import HelpModal from '../../components/HelpModal';
|
||||
import ProjectToolPanel from '../Tool-Panel';
|
||||
import SolutionForm from '../SolutionForm';
|
||||
import Spacer from '../../../../components/helpers/Spacer';
|
||||
import Spacer from '../../../../components/helpers/spacer';
|
||||
import { ChallengeNode } from '../../../../redux/prop-types';
|
||||
import { isSignedInSelector } from '../../../../redux';
|
||||
import Hotkeys from '../../components/Hotkeys';
|
||||
|
@ -22,7 +22,7 @@ import { getGuideUrl } from '../../utils';
|
||||
import LearnLayout from '../../../../components/layouts/Learn';
|
||||
import ChallengeTitle from '../../components/Challenge-Title';
|
||||
import ChallengeDescription from '../../components/Challenge-Description';
|
||||
import Spacer from '../../../../components/helpers/Spacer';
|
||||
import Spacer from '../../../../components/helpers/spacer';
|
||||
import SolutionForm from '../SolutionForm';
|
||||
import ProjectToolPanel from '../Tool-Panel';
|
||||
import CompletionModal from '../../components/CompletionModal';
|
||||
|
@ -17,10 +17,10 @@ import { ChallengeNode } from '../../../redux/prop-types';
|
||||
import LearnLayout from '../../../components/layouts/Learn';
|
||||
import ChallengeTitle from '../components/Challenge-Title';
|
||||
import ChallengeDescription from '../components/Challenge-Description';
|
||||
import Spacer from '../../../components/helpers/Spacer';
|
||||
import Spacer from '../../../components/helpers/spacer';
|
||||
import CompletionModal from '../components/CompletionModal';
|
||||
import Hotkeys from '../components/Hotkeys';
|
||||
import Loader from '../../../components/helpers/Loader';
|
||||
import Loader from '../../../components/helpers/loader';
|
||||
import {
|
||||
isChallengeCompletedSelector,
|
||||
challengeMounted,
|
||||
|
@ -6,8 +6,8 @@ import { Grid, ListGroup, ListGroupItem } from '@freecodecamp/react-bootstrap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import LearnLayout from '../../components/layouts/Learn';
|
||||
import FullWidthRow from '../../components/helpers/FullWidthRow';
|
||||
import ButtonSpacer from '../../components/helpers/ButtonSpacer';
|
||||
import FullWidthRow from '../../components/helpers/full-width-row';
|
||||
import ButtonSpacer from '../../components/helpers/button-spacer';
|
||||
import { MarkdownRemark, AllChallengeNode } from '../../redux/prop-types';
|
||||
|
||||
import './intro.css';
|
||||
|
@ -1,5 +1,10 @@
|
||||
{
|
||||
"include": ["./i18n/**/*", "./plugins/**/*","./src/**/*","./utils/**/*"],
|
||||
"include": [
|
||||
"./i18n/**/*",
|
||||
"./plugins/**/*",
|
||||
"./src/**/*",
|
||||
"./utils/**/*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"module": "es2020",
|
||||
@ -13,6 +18,10 @@
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["node", "jest", "@testing-library/jest-dom"]
|
||||
"types": [
|
||||
"node",
|
||||
"jest",
|
||||
"@testing-library/jest-dom"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user