mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(client): add local instructions for rdb courses (#59184)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@@ -509,6 +509,28 @@
|
||||
"learn-more": "Learn more about <0>Gitpod workspaces.</0>",
|
||||
"logout-warning": "If you log out of freeCodeCamp before you complete the entire {{course}} course, your progress will not be saved to your freeCodeCamp account."
|
||||
},
|
||||
"local": {
|
||||
"intro": "This course runs in a virtual Linux machine on your computer. To run the course, you first need to download each of the following if you don't already have them:",
|
||||
"download-vscode": "<0>VS Code</0> and the <1>Dev Containers</1> extension",
|
||||
"heading": "Then, follow these instructions to start the course:",
|
||||
"step-1": "Open a terminal and clone the RDB Alpha repo if you don't already have it with <0>git clone https://github.com/freeCodeCamp/rdb-alpha</0>",
|
||||
"step-2": "Navigate to the <0>rdb-alpha</0> directory in the terminal with <1>cd rdb-alpha</1>, and open VS Code with <2>code .</2>",
|
||||
"sub-step-heading": "If you want to save your progress to your freeCodeCamp account, do the following:",
|
||||
"sub-step-1": "Generate a user token if you don't already have one:",
|
||||
"generate-token-btn": "Generate User Token",
|
||||
"sub-step-2": "Copy your user token:",
|
||||
"copy-token-btn": "Copy User Token",
|
||||
"logout-warning": "If you log out of freeCodeCamp before you complete the entire {{course}} course, your user token will be deleted and your progress will not be saved to your freeCodeCamp account.",
|
||||
"sub-step-3": "In the VS Code that opened, find and open the file named <0>Dockerfile</0>. At the bottom of the file, paste your token in as the value for the <1>CODEROAD_WEBHOOK_TOKEN</1> variable. It should look like this: <2>ENV CODEROAD_WEBHOOK_TOKEN=your-token-here</2>",
|
||||
"step-3": "Open the command palette in VS Code by expanding the \"View\" menu and clicking \"Command Palette...\" and enter <0>Dev Containers: Rebuild and Reopen in Container</0> in the input.",
|
||||
"step-4": "A new VS Code window will open and begin building the Docker image. It will take several minutes the first time.",
|
||||
"step-5": "Once it is finished building, open the command palette again and enter <0>CodeRoad: Start</0> to open CodeRoad.",
|
||||
"step-6": "In the CodeRoad window, click \"Start New Tutorial\" and then the \"URL\" tab at the top.",
|
||||
"step-7": "Copy the course URL below, paste it in the URL input, and click \"Load\".",
|
||||
"copy-url": "Copy Course URL",
|
||||
"step-8": "Click \"Start\" to begin.",
|
||||
"step-9": "Follow the instructions in CodeRoad to complete the course. Note: You may need to restart the terminal once for terminal settings to take effect and the tests to pass."
|
||||
},
|
||||
"step-1": "Step 1: Complete the project",
|
||||
"step-2": "Step 2: Submit your code",
|
||||
"submit-public-url": "When you have completed the project, save all the required files into a public repository and submit the URL to it below.",
|
||||
@@ -918,6 +940,12 @@
|
||||
"generate-exam-error": "An error occurred trying to generate your exam.",
|
||||
"cert-not-found": "The certification {{certSlug}} does not exist.",
|
||||
"reset-editor-layout": "Your editor layout has been reset.",
|
||||
"user-token-generated": "A user token was created for you.",
|
||||
"user-token-generate-error": "Something went wrong trying to generate a user token for you.",
|
||||
"user-token-copied": "User token copied to clipboard.",
|
||||
"user-token-copy-error": "Something went wrong trying to copy your token.",
|
||||
"course-url-copied": "Course URL copied to clipboard.",
|
||||
"course-url-copy-error": "Something went wrong trying to copy the course URL.",
|
||||
"ms": {
|
||||
"transcript": {
|
||||
"link-err-1": "Please include a Microsoft transcript URL in the request.",
|
||||
|
||||
@@ -11,6 +11,8 @@ export enum FlashMessages {
|
||||
CodeSaveError = 'flash.code-save-error',
|
||||
CodeSaveLess = 'flash.code-save-less',
|
||||
CompleteProjectFirst = 'flash.complete-project-first',
|
||||
CourseUrlCopied = 'flash.course-url-copied',
|
||||
CourseUrlCopyError = 'flash.course-url-copy-error',
|
||||
DeleteTokenErr = 'flash.delete-token-err',
|
||||
EmailValid = 'flash.email-valid',
|
||||
GenerateExamError = 'flash.generate-exam-error',
|
||||
@@ -66,6 +68,10 @@ export enum FlashMessages {
|
||||
UsernameUpdated = 'flash.username-updated',
|
||||
UsernameUsed = 'flash.username-used',
|
||||
UserNotCertified = 'flash.user-not-certified',
|
||||
UserTokenCopied = 'flash.user-token-copied',
|
||||
UserTokenCopyError = 'flash.user-token-copy-error',
|
||||
UserTokenGenerated = 'flash.user-token-generated',
|
||||
UserTokenGenerateError = 'flash.user-token-generate-error',
|
||||
WrongName = 'flash.wrong-name',
|
||||
WrongUpdating = 'flash.wrong-updating',
|
||||
WentWrong = 'flash.went-wrong'
|
||||
|
||||
@@ -4,25 +4,34 @@ import React from 'react';
|
||||
import { useFeature } from '@growthbook/growthbook-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@freecodecamp/ui';
|
||||
import { challengeTypes } from '../../../../shared/config/challenge-types';
|
||||
|
||||
interface CodeAllyButtonProps {
|
||||
text: string;
|
||||
challengeType: number;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export function CodeAllyButton(props: CodeAllyButtonProps): JSX.Element | null {
|
||||
export function CodeAllyButton({
|
||||
challengeType,
|
||||
onClick
|
||||
}: CodeAllyButtonProps): JSX.Element | null {
|
||||
const codeAllyDisabledFeature = useFeature('codeally_disabled');
|
||||
const { t } = useTranslation();
|
||||
|
||||
const text =
|
||||
challengeType === challengeTypes.codeAllyCert
|
||||
? t('buttons.click-start-project')
|
||||
: t('buttons.click-start-course');
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={codeAllyDisabledFeature.on ? () => {} : props.onClick}
|
||||
onClick={codeAllyDisabledFeature.on ? () => {} : onClick}
|
||||
disabled={codeAllyDisabledFeature.on}
|
||||
variant='primary'
|
||||
block={true}
|
||||
>
|
||||
<span className='sr-only'>, {t('aria.opens-new-window')}</span>
|
||||
{props.text}
|
||||
{text}
|
||||
<FontAwesomeIcon icon={faExternalLinkAlt} />
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { Alert, Spacer } from '@freecodecamp/ui';
|
||||
|
||||
interface RdbGitpodContinueAlertProps {
|
||||
course: string;
|
||||
}
|
||||
|
||||
function RdbGitpodContinueAlert({
|
||||
course
|
||||
}: RdbGitpodContinueAlertProps): JSX.Element {
|
||||
return (
|
||||
<Alert variant='info'>
|
||||
<Trans values={{ course }} i18nKey='learn.gitpod.continue-project'>
|
||||
<a
|
||||
href='https://gitpod.io/workspaces'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
<Spacer size='m' />
|
||||
<Trans i18nKey='learn.gitpod.learn-more'>
|
||||
<a
|
||||
href='https://forum.freecodecamp.org/t/using-gitpod-in-the-curriculum/668669'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
RdbGitpodContinueAlert.displayName = 'RdbGitpodContinueAlert';
|
||||
|
||||
export default RdbGitpodContinueAlert;
|
||||
@@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
function RdbGitpodInstructions(): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className='ca-description'>
|
||||
<p>{t('learn.gitpod.intro')}</p>
|
||||
<ol>
|
||||
<li>
|
||||
<Trans i18nKey='learn.gitpod.step-1'>
|
||||
<a
|
||||
href='https://github.com/join'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
title={t('learn.source-code-link')}
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</li>
|
||||
<li>{t('learn.gitpod.step-2')}</li>
|
||||
<li>{t('learn.gitpod.step-3')}</li>
|
||||
<li>
|
||||
{t('learn.gitpod.step-4')}
|
||||
<ul>
|
||||
<li>{t('learn.gitpod.step-5')}</li>
|
||||
<li>{t('learn.gitpod.step-6')}</li>
|
||||
<li>{t('learn.gitpod.step-7')}</li>
|
||||
<li>{t('learn.gitpod.step-8')}</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>{t('learn.gitpod.step-9')}</li>
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
RdbGitpodInstructions.displayName = 'RdbGitpodInstructions';
|
||||
|
||||
export default RdbGitpodInstructions;
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Alert } from '@freecodecamp/ui';
|
||||
|
||||
interface RdbGitpodLogoutAlertProps {
|
||||
course: string;
|
||||
}
|
||||
|
||||
function RdbGitpodLogoutAlert({
|
||||
course
|
||||
}: RdbGitpodLogoutAlertProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Alert variant='danger'>
|
||||
{t('learn.gitpod.logout-warning', { course })}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
RdbGitpodLogoutAlert.displayName = 'RdbGitpodLogoutAlert';
|
||||
|
||||
export default RdbGitpodLogoutAlert;
|
||||
@@ -0,0 +1,212 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Spacer, Button } from '@freecodecamp/ui';
|
||||
import { postUserToken } from '../../../utils/ajax';
|
||||
import { createFlashMessage } from '../../../components/Flash/redux';
|
||||
import { FlashMessages } from '../../../components/Flash/redux/flash-messages';
|
||||
|
||||
import {
|
||||
isSignedInSelector,
|
||||
userTokenSelector
|
||||
} from '../../../redux/selectors';
|
||||
import { updateUserToken } from '../../../redux/actions';
|
||||
import { Link } from '../../../components/helpers';
|
||||
|
||||
import RdbLocalLogoutAlert from './rdb-local-logout-alert';
|
||||
|
||||
const mapStateToProps = (state: unknown) => ({
|
||||
isSignedIn: isSignedInSelector(state),
|
||||
userToken: userTokenSelector(state) as string | null
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
createFlashMessage,
|
||||
updateUserToken
|
||||
};
|
||||
|
||||
interface RdbLocalInstructionsProps {
|
||||
course: string;
|
||||
createFlashMessage: typeof createFlashMessage;
|
||||
isSignedIn: boolean;
|
||||
updateUserToken: (arg0: string) => void;
|
||||
url: string;
|
||||
userToken: string | null;
|
||||
}
|
||||
|
||||
function RdbLocalInstructions({
|
||||
course,
|
||||
createFlashMessage,
|
||||
isSignedIn,
|
||||
updateUserToken,
|
||||
url,
|
||||
userToken
|
||||
}: RdbLocalInstructionsProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const coderoadTutorial = `https://raw.githubusercontent.com/${url}/main/tutorial.json`;
|
||||
|
||||
const generateUserToken = async () => {
|
||||
const createUserTokenResponse = await postUserToken();
|
||||
const { data = { userToken: null } } = createUserTokenResponse;
|
||||
|
||||
if (data?.userToken) {
|
||||
updateUserToken(data.userToken);
|
||||
createFlashMessage({
|
||||
type: 'success',
|
||||
message: FlashMessages.UserTokenGenerated
|
||||
});
|
||||
} else {
|
||||
createFlashMessage({
|
||||
type: 'danger',
|
||||
message: FlashMessages.UserTokenGenerateError
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const copyUserToken = () => {
|
||||
navigator.clipboard.writeText(userToken ?? '').then(
|
||||
() => {
|
||||
createFlashMessage({
|
||||
type: 'success',
|
||||
message: FlashMessages.UserTokenCopied
|
||||
});
|
||||
},
|
||||
() => {
|
||||
createFlashMessage({
|
||||
type: 'danger',
|
||||
message: FlashMessages.UserTokenCopyError
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const copyUrl = () => {
|
||||
navigator.clipboard.writeText(coderoadTutorial ?? '').then(
|
||||
() => {
|
||||
createFlashMessage({
|
||||
type: 'success',
|
||||
message: FlashMessages.CourseUrlCopied
|
||||
});
|
||||
},
|
||||
() => {
|
||||
createFlashMessage({
|
||||
type: 'danger',
|
||||
message: FlashMessages.CourseUrlCopyError
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='ca-description'>
|
||||
<p>{t('learn.local.intro')}</p>
|
||||
<ul>
|
||||
<li>
|
||||
<Link external={true} to='https://docs.docker.com/engine/'>
|
||||
Docker Engine
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey='learn.local.download-vscode'>
|
||||
<Link external={true} to='https://code.visualstudio.com/download'>
|
||||
placeholder
|
||||
</Link>
|
||||
<Link
|
||||
external={true}
|
||||
to='https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers'
|
||||
>
|
||||
placeholder
|
||||
</Link>
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Link external={true} to='https://git-scm.com/downloads'>
|
||||
Git
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
<Spacer size='m' />
|
||||
<p>{t('learn.local.heading')}</p>
|
||||
<ol>
|
||||
<li>
|
||||
<Trans i18nKey='learn.local.step-1'>
|
||||
<code>placeholder</code>
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey='learn.local.step-2'>
|
||||
<code>placeholder</code>
|
||||
<code>placeholder</code>
|
||||
<code>placeholder</code>
|
||||
</Trans>
|
||||
</li>
|
||||
{isSignedIn && (
|
||||
<>
|
||||
<Spacer size='s' />
|
||||
<p>{t('learn.local.sub-step-heading')}</p>
|
||||
<ol>
|
||||
<li>{t('learn.local.sub-step-1')}</li>
|
||||
<Spacer size='xxs' />
|
||||
<Button
|
||||
disabled={!!userToken}
|
||||
block={true}
|
||||
onClick={() => void generateUserToken()}
|
||||
>
|
||||
{t('learn.local.generate-token-btn')}
|
||||
</Button>
|
||||
<Spacer size='xs' />
|
||||
<li>{t('learn.local.sub-step-2')}</li>
|
||||
<Spacer size='xxs' />
|
||||
<Button
|
||||
disabled={!userToken}
|
||||
block={true}
|
||||
onClick={copyUserToken}
|
||||
>
|
||||
{t('learn.local.copy-token-btn')}
|
||||
</Button>
|
||||
<Spacer size='xs' />
|
||||
<li>
|
||||
<Trans i18nKey='learn.local.sub-step-3'>
|
||||
<code>placeholder</code>
|
||||
<code>placeholder</code>
|
||||
<code>placeholder</code>
|
||||
</Trans>
|
||||
</li>
|
||||
<Spacer size='xs' />
|
||||
<RdbLocalLogoutAlert course={course} />
|
||||
</ol>
|
||||
<Spacer size='s' />
|
||||
</>
|
||||
)}
|
||||
<li>
|
||||
<Trans i18nKey='learn.local.step-3'>
|
||||
<code>placeholder</code>
|
||||
</Trans>
|
||||
</li>
|
||||
<li>{t('learn.local.step-4')}</li>
|
||||
<li>
|
||||
<Trans i18nKey='learn.local.step-5'>
|
||||
<code>placeholder</code>
|
||||
</Trans>
|
||||
</li>
|
||||
<li>{t('learn.local.step-6')}</li>
|
||||
<li>{t('learn.local.step-7')}</li>
|
||||
<Spacer size='xxs' />
|
||||
<Button block={true} onClick={copyUrl}>
|
||||
{t('learn.local.copy-url')}
|
||||
</Button>
|
||||
<Spacer size='xs' />
|
||||
<li>{t('learn.local.step-8')}</li>
|
||||
<li>{t('learn.local.step-9')}</li>
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
RdbLocalInstructions.displayName = 'RdbLocalInstructions';
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(RdbLocalInstructions);
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Alert } from '@freecodecamp/ui';
|
||||
|
||||
interface RdbLocalLogoutAlertProps {
|
||||
course: string;
|
||||
}
|
||||
|
||||
function RdbLocalLogoutAlert({
|
||||
course
|
||||
}: RdbLocalLogoutAlertProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Alert variant='danger'>
|
||||
{t('learn.local.logout-warning', { course })}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
RdbLocalLogoutAlert.displayName = 'RdbLocalLogoutAlert';
|
||||
|
||||
export default RdbLocalLogoutAlert;
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Spacer } from '@freecodecamp/ui';
|
||||
|
||||
import ChallengeHeading from '../components/challenge-heading';
|
||||
import PrismFormatted from '../components/prism-formatted';
|
||||
|
||||
interface RdbStep1InstructionsProps {
|
||||
instructions: string;
|
||||
isCompleted: boolean;
|
||||
}
|
||||
|
||||
function RdbStep1Instructions({
|
||||
instructions,
|
||||
isCompleted
|
||||
}: RdbStep1InstructionsProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<ChallengeHeading heading={t('learn.step-1')} isCompleted={isCompleted} />
|
||||
<Spacer size='m' />
|
||||
<div className='ca-description'>{t('learn.runs-in-vm')}</div>
|
||||
<Spacer size='m' />
|
||||
<PrismFormatted text={instructions} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
RdbStep1Instructions.displayName = 'RdbStep1Instructions';
|
||||
|
||||
export default RdbStep1Instructions;
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Spacer } from '@freecodecamp/ui';
|
||||
|
||||
import ChallengeHeading from '../components/challenge-heading';
|
||||
import PrismFormatted from '../components/prism-formatted';
|
||||
|
||||
interface RdbStep2InstructionsProps {
|
||||
notes: string;
|
||||
isCompleted: boolean;
|
||||
}
|
||||
|
||||
function RdbStep2Instructions({
|
||||
isCompleted,
|
||||
notes
|
||||
}: RdbStep2InstructionsProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<ChallengeHeading heading={t('learn.step-2')} isCompleted={isCompleted} />
|
||||
<Spacer size='m' />
|
||||
<div className='ca-description'>{t('learn.submit-public-url')}</div>
|
||||
<Spacer size='m' />
|
||||
<PrismFormatted text={notes} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
RdbStep2Instructions.displayName = 'RdbStep2Instructions';
|
||||
|
||||
export default RdbStep2Instructions;
|
||||
@@ -3,17 +3,17 @@ import { graphql } from 'gatsby';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import type { Dispatch } from 'redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { Container, Col, Row, Alert, Spacer } from '@freecodecamp/ui';
|
||||
import { Container, Col, Row, Spacer } from '@freecodecamp/ui';
|
||||
import { useFeature } from '@growthbook/growthbook-react';
|
||||
|
||||
// Local Utilities
|
||||
import LearnLayout from '../../../components/layouts/learn';
|
||||
import ChallengeTitle from '../components/challenge-title';
|
||||
import ChallengeHeading from '../components/challenge-heading';
|
||||
import PrismFormatted from '../components/prism-formatted';
|
||||
import { challengeTypes } from '../../../../../shared/config/challenge-types';
|
||||
import CompletionModal from '../components/completion-modal';
|
||||
@@ -48,9 +48,16 @@ import { FlashMessages } from '../../../components/Flash/redux/flash-messages';
|
||||
import { SuperBlocks } from '../../../../../shared/config/curriculum';
|
||||
import { CodeAllyDown } from '../../../components/growth-book/codeally-down';
|
||||
import { postUserToken } from '../../../utils/ajax';
|
||||
import { CodeAllyButton } from '../../../components/growth-book/codeally-button';
|
||||
|
||||
import RdbGitpodContinueAlert from './rdb-gitpod-continue-alert';
|
||||
import RdbGitpodInstructions from './rdb-gitpod-instructions';
|
||||
import RdbGitpodLogoutAlert from './rdb-gitpod-logout-alert';
|
||||
import RdbLocalInstructions from './rdb-local-instructions';
|
||||
import RdbStep1Instructions from './rdb-step-1-instructions';
|
||||
import RdbStep2Instructions from './rdb-step-2-instructions';
|
||||
|
||||
import './codeally.css';
|
||||
import { CodeAllyButton } from '../../../components/growth-book/codeally-button';
|
||||
|
||||
// Redux
|
||||
const mapStateToProps = createSelector(
|
||||
@@ -125,7 +132,8 @@ function ShowCodeAlly(props: ShowCodeAllyProps) {
|
||||
notes,
|
||||
superBlock,
|
||||
title,
|
||||
translationPending
|
||||
translationPending,
|
||||
url
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -261,6 +269,8 @@ function ShowCodeAlly(props: ShowCodeAllyProps) {
|
||||
}
|
||||
};
|
||||
|
||||
const gitpodDeprecated = useFeature('gitpod-deprecated').on;
|
||||
|
||||
return (
|
||||
<Hotkeys containerRef={container}>
|
||||
<LearnLayout>
|
||||
@@ -280,121 +290,92 @@ function ShowCodeAlly(props: ShowCodeAllyProps) {
|
||||
<Spacer size='m' />
|
||||
<PrismFormatted text={description} />
|
||||
<Spacer size='m' />
|
||||
<div className='ca-description'>
|
||||
<p>{t('learn.gitpod.intro')}</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<Trans i18nKey='learn.gitpod.step-1'>
|
||||
<a
|
||||
href='https://github.com/join'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
title={t('learn.source-code-link')}
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</li>
|
||||
|
||||
<li>{t('learn.gitpod.step-2')}</li>
|
||||
<li>{t('learn.gitpod.step-3')}</li>
|
||||
<li>
|
||||
{t('learn.gitpod.step-4')}
|
||||
<ul>
|
||||
<li>{t('learn.gitpod.step-5')}</li>
|
||||
<li>{t('learn.gitpod.step-6')}</li>
|
||||
<li>{t('learn.gitpod.step-7')}</li>
|
||||
<li>{t('learn.gitpod.step-8')}</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>{t('learn.gitpod.step-9')}</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<Spacer size='m' />
|
||||
{isSignedIn && challengeType === challengeTypes.codeAllyCert && (
|
||||
{gitpodDeprecated ? (
|
||||
<>
|
||||
<div className='ca-description'>
|
||||
{t('learn.complete-both-steps')}
|
||||
</div>
|
||||
<hr />
|
||||
<RdbLocalInstructions course={title} url={url} />
|
||||
<Spacer size='m' />
|
||||
<ChallengeHeading
|
||||
heading={t('learn.step-1')}
|
||||
isCompleted={isPartiallyCompleted || isCompleted}
|
||||
/>
|
||||
<Spacer size='m' />
|
||||
<div className='ca-description'>{t('learn.runs-in-vm')}</div>
|
||||
<Spacer size='m' />
|
||||
<PrismFormatted text={instructions} />
|
||||
{isSignedIn &&
|
||||
challengeType === challengeTypes.codeAllyCert && (
|
||||
<>
|
||||
<div className='ca-description'>
|
||||
{t('learn.complete-both-steps')}
|
||||
</div>
|
||||
<hr />
|
||||
<Spacer size='m' />
|
||||
<RdbStep1Instructions
|
||||
instructions={instructions}
|
||||
isCompleted={isPartiallyCompleted || isCompleted}
|
||||
/>
|
||||
<hr />
|
||||
<Spacer size='m' />
|
||||
<RdbStep2Instructions
|
||||
isCompleted={isCompleted}
|
||||
notes={notes}
|
||||
/>
|
||||
<Spacer size='m' />
|
||||
<SolutionForm
|
||||
challengeType={challengeType}
|
||||
description={description}
|
||||
onSubmit={handleSubmit}
|
||||
updateSolutionForm={updateSolutionFormValues}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<RdbGitpodInstructions />
|
||||
<Spacer size='m' />
|
||||
{isSignedIn &&
|
||||
challengeType === challengeTypes.codeAllyCert ? (
|
||||
<>
|
||||
<div className='ca-description'>
|
||||
{t('learn.complete-both-steps')}
|
||||
</div>
|
||||
<hr />
|
||||
<Spacer size='m' />
|
||||
<RdbStep1Instructions
|
||||
instructions={instructions}
|
||||
isCompleted={isPartiallyCompleted || isCompleted}
|
||||
/>
|
||||
<Spacer size='m' />
|
||||
<RdbGitpodContinueAlert course={title} />
|
||||
{isSignedIn && <RdbGitpodLogoutAlert course={title} />}
|
||||
<CodeAllyButton
|
||||
challengeType={challengeType}
|
||||
//eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
onClick={startCourse}
|
||||
/>
|
||||
<hr />
|
||||
<Spacer size='m' />
|
||||
<RdbStep2Instructions
|
||||
isCompleted={isCompleted}
|
||||
notes={notes}
|
||||
/>
|
||||
<Spacer size='m' />
|
||||
<SolutionForm
|
||||
challengeType={challengeType}
|
||||
description={description}
|
||||
onSubmit={handleSubmit}
|
||||
updateSolutionForm={updateSolutionFormValues}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<RdbGitpodContinueAlert course={title} />
|
||||
{isSignedIn && <RdbGitpodLogoutAlert course={title} />}
|
||||
<CodeAllyButton
|
||||
challengeType={challengeType}
|
||||
//eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
onClick={startCourse}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Spacer size='xxs' />
|
||||
</>
|
||||
)}
|
||||
<Alert variant='info'>
|
||||
<Trans
|
||||
values={{ course: title }}
|
||||
i18nKey='learn.gitpod.continue-project'
|
||||
>
|
||||
<a
|
||||
href='https://gitpod.io/workspaces'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
<Spacer size='m' />
|
||||
<Trans i18nKey='learn.gitpod.learn-more'>
|
||||
<a
|
||||
href='https://forum.freecodecamp.org/t/using-gitpod-in-the-curriculum/668669'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</Alert>
|
||||
{isSignedIn && (
|
||||
<Alert variant='danger'>
|
||||
{t('learn.gitpod.logout-warning', { course: title })}
|
||||
</Alert>
|
||||
)}
|
||||
<CodeAllyButton
|
||||
text={
|
||||
challengeType === challengeTypes.codeAllyCert
|
||||
? t('buttons.click-start-project')
|
||||
: t('buttons.click-start-course')
|
||||
}
|
||||
// `this.startCourse` being an async callback is acceptable
|
||||
//eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
onClick={startCourse}
|
||||
/>
|
||||
{isSignedIn && challengeType === challengeTypes.codeAllyCert && (
|
||||
<>
|
||||
<hr />
|
||||
<Spacer size='m' />
|
||||
<ChallengeHeading
|
||||
heading={t('learn.step-2')}
|
||||
isCompleted={isCompleted}
|
||||
/>
|
||||
<Spacer size='m' />
|
||||
<div className='ca-description'>
|
||||
{t('learn.submit-public-url')}
|
||||
</div>
|
||||
<Spacer size='m' />
|
||||
<PrismFormatted text={notes} />
|
||||
<Spacer size='m' />
|
||||
<SolutionForm
|
||||
challengeType={challengeType}
|
||||
description={description}
|
||||
onSubmit={handleSubmit}
|
||||
updateSolutionForm={updateSolutionFormValues}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Spacer size='xxs' />
|
||||
|
||||
<ProjectToolPanel />
|
||||
<br />
|
||||
<Spacer size='m' />
|
||||
|
||||
@@ -25,6 +25,8 @@ const toneUrls = {
|
||||
[FlashMessages.CodeSaveError]: TRY_AGAIN,
|
||||
[FlashMessages.CodeSaveLess]: TRY_AGAIN,
|
||||
[FlashMessages.CompleteProjectFirst]: TRY_AGAIN,
|
||||
[FlashMessages.CourseUrlCopied]: CHAL_COMP,
|
||||
[FlashMessages.CourseUrlCopyError]: TRY_AGAIN,
|
||||
[FlashMessages.DeleteTokenErr]: TRY_AGAIN,
|
||||
[FlashMessages.EmailValid]: CHAL_COMP,
|
||||
[FlashMessages.GenerateExamError]: TRY_AGAIN,
|
||||
@@ -80,6 +82,10 @@ const toneUrls = {
|
||||
[FlashMessages.UsernameUpdated]: CHAL_COMP,
|
||||
[FlashMessages.UsernameUsed]: TRY_AGAIN,
|
||||
[FlashMessages.UserNotCertified]: TRY_AGAIN,
|
||||
[FlashMessages.UserTokenCopied]: CHAL_COMP,
|
||||
[FlashMessages.UserTokenCopyError]: TRY_AGAIN,
|
||||
[FlashMessages.UserTokenGenerated]: CHAL_COMP,
|
||||
[FlashMessages.UserTokenGenerateError]: TRY_AGAIN,
|
||||
[FlashMessages.WrongName]: TRY_AGAIN,
|
||||
[FlashMessages.WrongUpdating]: TRY_AGAIN,
|
||||
[FlashMessages.WentWrong]: TRY_AGAIN
|
||||
|
||||
Reference in New Issue
Block a user