mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(client): add gp instructions for rdb (#53612)
Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
@@ -1449,7 +1449,7 @@
|
||||
"legacy-go-back": "Go to the current version of the curriculum.",
|
||||
"course-maintenance": "These courses are undergoing maintenance. If they are not working, you can learn how to run them locally at <0>https://www.freecodecamp.org/news/how-to-run-freecodecamps-relational-databases-curriculum-using-docker-vscode-and-coderoad</0>.",
|
||||
"course-disabling-soon": "The browser version of these courses will be temporarily disabled soon and your virtual machines will be deleted. Any progress in your virtual machines will be lost. If you have any files you want from them, you should save them to your computer. We apologize for any inconvenience. We hope to have an improved browser version of these courses available again in the next few weeks.",
|
||||
"course-disabled": "These courses are temporarily unavailable to run in the browser. We apologize for any inconvenience. You can learn how to run them locally at <0>https://www.freecodecamp.org/news/how-to-run-freecodecamps-relational-databases-curriculum-using-docker-vscode-and-coderoad</0>. We hope to have an improved browser version available again in the next few weeks.",
|
||||
"course-disabled": "These courses are temporarily unavailable to run in the browser. We apologize for any inconvenience. You can learn how to run them locally at <0>https://www.freecodecamp.org/news/how-to-run-freecodecamps-relational-databases-curriculum-using-docker-vscode-and-coderoad</0>. We hope to have an improved browser version available again soon.",
|
||||
"run-locally": "For now, we recommend running the courses locally on your computer. You can learn how at <0>https://www.freecodecamp.org/news/how-to-run-freecodecamps-relational-databases-curriculum-using-docker-vscode-and-coderoad</0>.",
|
||||
"progress-wont-save": "Your progress will not be saved to your freeCodeCamp account when running them locally.",
|
||||
"go-back-to-learn": "Go back to the stable version of the curriculum.",
|
||||
|
||||
@@ -416,6 +416,21 @@
|
||||
"help-translate-link": "Help us translate.",
|
||||
"project-preview-title": "Here's a preview of what you will build",
|
||||
"github-required": "<0>Create a GitHub</0> account if you don't have one. You'll need it when you create the virtual Linux server machine. This process may take a few minutes.",
|
||||
"gitpod": {
|
||||
"intro": "This course runs in a virtual Linux machine using Gitpod. Follow these instructions to start the course:",
|
||||
"step-1": "<0>Create a GitHub</0> account if you don't have one",
|
||||
"step-2": "Click the start button below",
|
||||
"step-3": "Login to Gitpod with your GitHub account if you aren't already",
|
||||
"step-4": "Once the virtual Linux machine is finished loading, start the CodeRoad extension by:",
|
||||
"step-5": "Clicking the \"hamburger\" menu near the top left of the VSCode window,",
|
||||
"step-6": "Going to the \"View\" menu,",
|
||||
"step-7": "Clicking on the \"Command Palette\" option,",
|
||||
"step-8": "and running the \"CodeRoad: Start\" command",
|
||||
"step-9": "Follow the instructions in CodeRoad to complete the course",
|
||||
"continue-project": "Clicking the button below will start a new project. If you have previously started the {{course}} course, go to <0>your Gitpod dashboard</0> to continue.",
|
||||
"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."
|
||||
},
|
||||
"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.",
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import React from 'react';
|
||||
import { useFeature } from '@growthbook/growthbook-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@freecodecamp/ui';
|
||||
|
||||
interface CodeAllyButtonProps {
|
||||
onClick: () => void;
|
||||
text: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export function CodeAllyButton(props: CodeAllyButtonProps): JSX.Element | null {
|
||||
const codeAllyDisabledFeature = useFeature('codeally_disabled');
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Button
|
||||
aria-describedby='codeally-cookie-warning'
|
||||
block={true}
|
||||
variant='primary'
|
||||
data-cy='start-codeally'
|
||||
onClick={codeAllyDisabledFeature.on ? () => {} : props.onClick}
|
||||
disabled={codeAllyDisabledFeature.on}
|
||||
onClick={props.onClick}
|
||||
variant='primary'
|
||||
block={true}
|
||||
>
|
||||
{props.text}
|
||||
<span className='sr-only'>, {t('aria.opens-new-window')}</span>
|
||||
{props.text}
|
||||
<FontAwesomeIcon icon={faExternalLinkAlt} />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,29 +25,6 @@ const Down = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const DisablingSoon = () => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Alert variant='danger'>
|
||||
<p>{t('intro:misc-text.course-disabling-soon')}</p>
|
||||
<Spacer size='small' />
|
||||
<p>
|
||||
<Trans i18nKey='intro:misc-text.run-locally'>
|
||||
<a
|
||||
href='https://www.freecodecamp.org/news/how-to-run-freecodecamps-relational-databases-curriculum-using-docker-vscode-and-coderoad'
|
||||
rel='noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</p>
|
||||
<Spacer size='small' />
|
||||
<p>{t('intro:misc-text.progress-wont-save')}</p>
|
||||
</Alert>
|
||||
);
|
||||
};
|
||||
|
||||
const Disabled = () => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
@@ -71,13 +48,10 @@ const Disabled = () => {
|
||||
|
||||
export function CodeAllyDown(): JSX.Element | null {
|
||||
const codeAllyDownFeature = useFeature('codeally_down');
|
||||
const codeAllyDisablingSoonFeature = useFeature('codeally_disabling_soon');
|
||||
const codeAllyDisabledFeature = useFeature('codeally_disabled');
|
||||
|
||||
return codeAllyDisabledFeature.on ? (
|
||||
<Disabled />
|
||||
) : codeAllyDisablingSoonFeature.on ? (
|
||||
<DisablingSoon />
|
||||
) : codeAllyDownFeature.on ? (
|
||||
<Down />
|
||||
) : null;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useFeature } from '@growthbook/growthbook-react';
|
||||
|
||||
interface CodeAllyIframeProps {
|
||||
src: string;
|
||||
}
|
||||
|
||||
export function CodeAllyIframe(props: CodeAllyIframeProps): JSX.Element | null {
|
||||
const codeAllyDisabledFeature = useFeature('codeally_disabled');
|
||||
|
||||
return codeAllyDisabledFeature.on ? null : (
|
||||
<iframe
|
||||
className='codeally-frame'
|
||||
data-cy='codeally-frame'
|
||||
name={`codeAlly${Date.now()}`}
|
||||
sandbox='allow-modals allow-forms allow-popups allow-scripts allow-same-origin'
|
||||
src={props.src}
|
||||
title='Editor'
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
userSelector,
|
||||
isOnlineSelector,
|
||||
isServerOnlineSelector,
|
||||
showCodeAllySelector,
|
||||
userFetchStateSelector
|
||||
} from '../../redux/selectors';
|
||||
|
||||
@@ -60,7 +59,6 @@ const mapStateToProps = createSelector(
|
||||
isOnlineSelector,
|
||||
isServerOnlineSelector,
|
||||
userFetchStateSelector,
|
||||
showCodeAllySelector,
|
||||
userSelector,
|
||||
(
|
||||
isSignedIn,
|
||||
@@ -69,7 +67,6 @@ const mapStateToProps = createSelector(
|
||||
isOnline: boolean,
|
||||
isServerOnline: boolean,
|
||||
fetchState: UserFetchState,
|
||||
showCodeAlly: boolean,
|
||||
user: User
|
||||
) => ({
|
||||
isSignedIn,
|
||||
@@ -80,7 +77,6 @@ const mapStateToProps = createSelector(
|
||||
isServerOnline,
|
||||
fetchState,
|
||||
theme: user.theme,
|
||||
showCodeAlly,
|
||||
user
|
||||
})
|
||||
);
|
||||
@@ -108,7 +104,6 @@ interface DefaultLayoutProps extends StateProps, DispatchProps {
|
||||
isChallenge?: boolean;
|
||||
block?: string;
|
||||
examInProgress: boolean;
|
||||
showCodeAlly: boolean;
|
||||
superBlock?: string;
|
||||
}
|
||||
|
||||
@@ -134,7 +129,6 @@ function DefaultLayout({
|
||||
block,
|
||||
superBlock,
|
||||
theme,
|
||||
showCodeAlly,
|
||||
user,
|
||||
fetchUser,
|
||||
updateAllChallengesInfo
|
||||
@@ -248,7 +242,7 @@ function DefaultLayout({
|
||||
/>
|
||||
) : null}
|
||||
<SignoutModal />
|
||||
{isChallenge && !showCodeAlly && !examInProgress && (
|
||||
{isChallenge && !examInProgress && (
|
||||
<div className='breadcrumbs-demo'>
|
||||
<BreadCrumb
|
||||
block={block as string}
|
||||
|
||||
@@ -31,13 +31,6 @@ body {
|
||||
min-height: 80vh;
|
||||
}
|
||||
|
||||
.codeally-frame {
|
||||
display: block;
|
||||
height: calc(100vh - var(--header-height));
|
||||
width: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.btn-cta-big {
|
||||
max-height: 100%;
|
||||
font-size: 1.5rem;
|
||||
|
||||
@@ -8,7 +8,6 @@ export const actionTypes = createTypes(
|
||||
'hardGoTo',
|
||||
'allowBlockDonationRequests',
|
||||
'setRenderStartTime',
|
||||
'hideCodeAlly',
|
||||
'preventBlockDonationRequests',
|
||||
'setCompletionCountWhenShownProgressModal',
|
||||
'setShowMultipleProgressModals',
|
||||
@@ -19,10 +18,8 @@ export const actionTypes = createTypes(
|
||||
'onlineStatusChange',
|
||||
'serverStatusChange',
|
||||
'resetUserData',
|
||||
'tryToShowCodeAlly',
|
||||
'tryToShowDonationModal',
|
||||
'executeGA',
|
||||
'showCodeAlly',
|
||||
'startExam',
|
||||
'stopExam',
|
||||
'clearExamResults',
|
||||
|
||||
@@ -101,10 +101,6 @@ export const deleteUserTokenComplete = createAction(
|
||||
actionTypes.deleteUserTokenComplete
|
||||
);
|
||||
|
||||
export const hideCodeAlly = createAction(actionTypes.hideCodeAlly);
|
||||
export const showCodeAlly = createAction(actionTypes.showCodeAlly);
|
||||
export const tryToShowCodeAlly = createAction(actionTypes.tryToShowCodeAlly);
|
||||
|
||||
export const startExam = createAction(actionTypes.startExam);
|
||||
export const stopExam = createAction(actionTypes.stopExam);
|
||||
export const clearExamResults = createAction(actionTypes.clearExamResults);
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import { call, put, select, takeEvery } from 'redux-saga/effects';
|
||||
|
||||
import { createFlashMessage } from '../components/Flash/redux';
|
||||
import { FlashMessages } from '../components/Flash/redux/flash-messages';
|
||||
import { postUserToken } from '../utils/ajax';
|
||||
import { showCodeAlly, updateUserToken } from './actions';
|
||||
import { isSignedInSelector, userTokenSelector } from './selectors';
|
||||
|
||||
const startProjectErrMessage = {
|
||||
type: 'danger',
|
||||
message: FlashMessages.StartProjectErr
|
||||
};
|
||||
|
||||
function* tryToShowCodeAllySaga() {
|
||||
const isSignedIn = yield select(isSignedInSelector);
|
||||
const hasUserToken = !!(yield select(userTokenSelector));
|
||||
|
||||
if (!isSignedIn || hasUserToken) {
|
||||
yield put(showCodeAlly());
|
||||
} else {
|
||||
try {
|
||||
const { data } = yield call(postUserToken);
|
||||
|
||||
if (data?.userToken) {
|
||||
yield put(updateUserToken(data.userToken));
|
||||
yield put(showCodeAlly());
|
||||
} else {
|
||||
yield put(createFlashMessage(startProjectErrMessage));
|
||||
}
|
||||
} catch (e) {
|
||||
yield put(createFlashMessage(startProjectErrMessage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createCodeAllySaga(types) {
|
||||
return [takeEvery(types.tryToShowCodeAlly, tryToShowCodeAllySaga)];
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
import { createAcceptTermsSaga } from './accept-terms-saga';
|
||||
import { actionTypes, ns as MainApp } from './action-types';
|
||||
import { createAppMountSaga } from './app-mount-saga';
|
||||
import { createCodeAllySaga } from './codeally-saga';
|
||||
import { createDonationSaga } from './donation-saga';
|
||||
import failedUpdatesEpic from './failed-updates-epic';
|
||||
import { createFetchUserSaga } from './fetch-user-saga';
|
||||
@@ -63,7 +62,6 @@ const initialState = {
|
||||
showCertFetchState: {
|
||||
...defaultFetchState
|
||||
},
|
||||
showCodeAlly: false,
|
||||
user: {},
|
||||
userFetchState: {
|
||||
...defaultFetchState
|
||||
@@ -93,7 +91,6 @@ export const epics = [hardGoToEpic, failedUpdatesEpic, updateCompleteEpic];
|
||||
export const sagas = [
|
||||
...createAcceptTermsSaga(actionTypes),
|
||||
...createAppMountSaga(actionTypes),
|
||||
...createCodeAllySaga(actionTypes),
|
||||
...createDonationSaga(actionTypes),
|
||||
...createGaSaga(actionTypes),
|
||||
...createFetchUserSaga(actionTypes),
|
||||
@@ -418,18 +415,6 @@ export const reducer = handleActions(
|
||||
}
|
||||
};
|
||||
},
|
||||
[actionTypes.hideCodeAlly]: state => {
|
||||
return {
|
||||
...state,
|
||||
showCodeAlly: false
|
||||
};
|
||||
},
|
||||
[actionTypes.showCodeAlly]: state => {
|
||||
return {
|
||||
...state,
|
||||
showCodeAlly: true
|
||||
};
|
||||
},
|
||||
[actionTypes.startExam]: state => {
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -78,10 +78,6 @@ export const userTokenSelector = state => {
|
||||
return userSelector(state).userToken;
|
||||
};
|
||||
|
||||
export const showCodeAllySelector = state => {
|
||||
return state[MainApp].showCodeAlly;
|
||||
};
|
||||
|
||||
export const examInProgressSelector = state => {
|
||||
return state[MainApp].examInProgress;
|
||||
};
|
||||
|
||||
@@ -20,11 +20,10 @@ import { challengeTypes } from '../../../../../shared/config/challenge-types';
|
||||
import CompletionModal from '../components/completion-modal';
|
||||
import HelpModal from '../components/help-modal';
|
||||
import Hotkeys from '../components/hotkeys';
|
||||
import { hideCodeAlly, tryToShowCodeAlly } from '../../../redux/actions';
|
||||
import { updateUserToken } from '../../../redux/actions';
|
||||
import {
|
||||
completedChallengesSelector,
|
||||
partiallyCompletedChallengesSelector,
|
||||
showCodeAllySelector,
|
||||
isSignedInSelector,
|
||||
userTokenSelector
|
||||
} from '../../../redux/selectors';
|
||||
@@ -46,9 +45,9 @@ import SolutionForm from '../projects/solution-form';
|
||||
import { FlashMessages } from '../../../components/Flash/redux/flash-messages';
|
||||
import { SuperBlocks } from '../../../../../shared/config/superblocks';
|
||||
import { CodeAllyDown } from '../../../components/growth-book/codeally-down';
|
||||
import { postUserToken } from '../../../utils/ajax';
|
||||
|
||||
import './codeally.css';
|
||||
import { CodeAllyIframe } from '../../../components/growth-book/codeally-iframe';
|
||||
import { CodeAllyButton } from '../../../components/growth-book/codeally-button';
|
||||
|
||||
// Redux
|
||||
@@ -57,21 +56,18 @@ const mapStateToProps = createSelector(
|
||||
isChallengeCompletedSelector,
|
||||
isSignedInSelector,
|
||||
partiallyCompletedChallengesSelector,
|
||||
showCodeAllySelector,
|
||||
userTokenSelector,
|
||||
(
|
||||
completedChallenges: CompletedChallenge[],
|
||||
isChallengeCompleted: boolean,
|
||||
isSignedIn: boolean,
|
||||
partiallyCompletedChallenges: CompletedChallenge[],
|
||||
showCodeAlly: boolean,
|
||||
userToken: string | null
|
||||
) => ({
|
||||
completedChallenges,
|
||||
isChallengeCompleted,
|
||||
isSignedIn,
|
||||
partiallyCompletedChallenges,
|
||||
showCodeAlly,
|
||||
userToken
|
||||
})
|
||||
);
|
||||
@@ -81,9 +77,8 @@ const mapDispatchToProps = (dispatch: Dispatch) =>
|
||||
{
|
||||
challengeMounted,
|
||||
createFlashMessage,
|
||||
hideCodeAlly,
|
||||
openCompletionModal: () => openModal('completion'),
|
||||
tryToShowCodeAlly,
|
||||
updateUserToken,
|
||||
updateChallengeMeta,
|
||||
updateSolutionFormValues
|
||||
},
|
||||
@@ -96,7 +91,6 @@ interface ShowCodeAllyProps {
|
||||
completedChallenges: CompletedChallenge[];
|
||||
createFlashMessage: typeof createFlashMessage;
|
||||
data: { challengeNode: ChallengeNode };
|
||||
hideCodeAlly: () => void;
|
||||
isChallengeCompleted: boolean;
|
||||
isSignedIn: boolean;
|
||||
openCompletionModal: () => void;
|
||||
@@ -104,10 +98,9 @@ interface ShowCodeAllyProps {
|
||||
challengeMeta: ChallengeMeta;
|
||||
};
|
||||
partiallyCompletedChallenges: CompletedChallenge[];
|
||||
showCodeAlly: boolean;
|
||||
t: TFunction;
|
||||
tryToShowCodeAlly: () => void;
|
||||
updateChallengeMeta: (arg0: ChallengeMeta) => void;
|
||||
updateUserToken: (arg0: string) => void;
|
||||
updateSolutionFormValues: () => void;
|
||||
userToken: string | null;
|
||||
}
|
||||
@@ -137,10 +130,6 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
this.container.current?.focus();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.hideCodeAlly();
|
||||
}
|
||||
|
||||
handleSubmit = ({
|
||||
showCompletionModal
|
||||
}: {
|
||||
@@ -176,6 +165,49 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
}
|
||||
};
|
||||
|
||||
openGitpod = (userToken?: string) => {
|
||||
const {
|
||||
data: {
|
||||
challengeNode: {
|
||||
challenge: { url }
|
||||
}
|
||||
}
|
||||
} = this.props;
|
||||
|
||||
const repoUrl = `https://github.com/${url}`;
|
||||
const coderoadTutorial = encodeURIComponent(
|
||||
`https://raw.githubusercontent.com/${url}/main/tutorial.json`
|
||||
);
|
||||
const gitpodDomain = `https://gitpod.io/?autostart=true#CODEROAD_TUTORIAL_URL=${coderoadTutorial},CODEROAD_DISABLE_RUN_ON_SAVE=true`;
|
||||
const tokenEnv = userToken ? `,CODEROAD_WEBHOOK_TOKEN=${userToken}` : '';
|
||||
const gitpodUrl = `${gitpodDomain}${tokenEnv}/${repoUrl}`;
|
||||
|
||||
window.open(gitpodUrl, '_blank');
|
||||
};
|
||||
|
||||
startCourse = async () => {
|
||||
const { isSignedIn, userToken, updateUserToken } = this.props;
|
||||
|
||||
if (!isSignedIn) {
|
||||
this.openGitpod();
|
||||
} else if (!userToken) {
|
||||
const createUserTokenResponse = await postUserToken();
|
||||
const { data = { userToken: null } } = createUserTokenResponse;
|
||||
|
||||
if (data?.userToken) {
|
||||
updateUserToken(data.userToken);
|
||||
this.openGitpod(data.userToken);
|
||||
} else {
|
||||
createFlashMessage({
|
||||
type: 'danger',
|
||||
message: FlashMessages.StartProjectErr
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.openGitpod(userToken);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
completedChallenges,
|
||||
@@ -190,8 +222,7 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
notes,
|
||||
superBlock,
|
||||
title,
|
||||
translationPending,
|
||||
url
|
||||
translationPending
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -201,11 +232,8 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
challengeMeta: { nextChallengePath, prevChallengePath }
|
||||
},
|
||||
partiallyCompletedChallenges,
|
||||
showCodeAlly,
|
||||
t,
|
||||
tryToShowCodeAlly,
|
||||
updateSolutionFormValues,
|
||||
userToken = null
|
||||
updateSolutionFormValues
|
||||
} = this.props;
|
||||
|
||||
const blockNameTitle = `${t(
|
||||
@@ -213,22 +241,6 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
)}: ${title}`;
|
||||
const windowTitle = `${blockNameTitle} | freeCodeCamp.org`;
|
||||
|
||||
// Initial CodeAlly login includes a tempToken in redirect URL
|
||||
const queryParams = new URLSearchParams(window.location.search);
|
||||
const codeAllyTempToken: string | null = queryParams.get('tempToken');
|
||||
|
||||
const tempToken = codeAllyTempToken ? `tempToken=${codeAllyTempToken}` : '';
|
||||
|
||||
// Include a unique param to avoid CodeAlly caching issues
|
||||
const date = `date=${Date.now()}`;
|
||||
|
||||
// User token for submitting CodeRoad tutorials
|
||||
const envVariables = userToken
|
||||
? `envVariables=CODEROAD_WEBHOOK_TOKEN=${userToken}`
|
||||
: '';
|
||||
|
||||
const goBackTo = `goBackTo=${window.location.href}`;
|
||||
|
||||
const isPartiallyCompleted = partiallyCompletedChallenges.some(
|
||||
challenge => challenge.id === challengeId
|
||||
);
|
||||
@@ -236,15 +248,8 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
const isCompleted = completedChallenges.some(
|
||||
challenge => challenge.id === challengeId
|
||||
);
|
||||
const titleContext = t('learn.source-code-link');
|
||||
return showCodeAlly ? (
|
||||
<LearnLayout>
|
||||
<Helmet title={windowTitle} />
|
||||
<CodeAllyIframe
|
||||
src={`https://codeally.io/embed/?repoUrl=${url}&${goBackTo}&${envVariables}&${tempToken}&${date}`}
|
||||
/>
|
||||
</LearnLayout>
|
||||
) : (
|
||||
|
||||
return (
|
||||
<Hotkeys
|
||||
containerRef={this.container}
|
||||
nextChallengePath={nextChallengePath}
|
||||
@@ -268,17 +273,38 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
<PrismFormatted text={description} />
|
||||
<Spacer size='medium' />
|
||||
<div className='ca-description'>
|
||||
<Trans i18nKey='learn.github-required'>
|
||||
<a
|
||||
href='https://github.com/join'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
title={titleContext}
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
<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='medium' />
|
||||
{isSignedIn &&
|
||||
challengeType === challengeTypes.codeAllyCert && (
|
||||
@@ -301,16 +327,45 @@ class ShowCodeAlly extends Component<ShowCodeAllyProps> {
|
||||
<Spacer size='medium' />
|
||||
</>
|
||||
)}
|
||||
<Alert id='codeally-cookie-warning' variant='info'>
|
||||
<p>{t(`intro:misc-text.enable-cookies`)}</p>
|
||||
<Alert variant='info'>
|
||||
<p>
|
||||
<Trans
|
||||
values={{ course: title }}
|
||||
i18nKey='learn.gitpod.continue-project'
|
||||
>
|
||||
<a
|
||||
href='https://gitpod.io/workspaces'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
placeholder
|
||||
</a>
|
||||
</Trans>
|
||||
</p>
|
||||
<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
|
||||
onClick={tryToShowCodeAlly}
|
||||
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={this.startCourse}
|
||||
/>
|
||||
{isSignedIn &&
|
||||
challengeType === challengeTypes.codeAllyCert && (
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Alert } from '@freecodecamp/ui';
|
||||
import { useFeature } from '@growthbook/growthbook-react';
|
||||
import { SuperBlocks } from '../../../../../shared/config/superblocks';
|
||||
import { isOldRespCert, isRelationalDbCert } from '../../../utils/is-a-cert';
|
||||
import { Link } from '../../../components/helpers';
|
||||
@@ -18,7 +17,6 @@ interface LegacyLinksProps {
|
||||
|
||||
function LegacyLinks({ superBlock }: LegacyLinksProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const codeAllyDisabledFeature = useFeature('codeally_disabled');
|
||||
|
||||
if (isOldRespCert(superBlock)) {
|
||||
return (
|
||||
@@ -42,19 +40,6 @@ function LegacyLinks({ superBlock }: LegacyLinksProps): JSX.Element {
|
||||
<p>{t('intro:misc-text.english-only')}</p>
|
||||
</Alert>
|
||||
)}
|
||||
{codeAllyDisabledFeature.on ? null : (
|
||||
<Alert variant='info'>
|
||||
<p>
|
||||
<Link
|
||||
external={true}
|
||||
sameTab={false}
|
||||
to={`https://forum.freecodecamp.org/t/how-to-troubleshoot-the-web-version-of-the-relational-database-curriculum/500231`}
|
||||
>
|
||||
{t('intro:misc-text.read-database-cert-article')}
|
||||
</Link>
|
||||
</p>
|
||||
</Alert>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5f1a4ef5d5d6b5ab580fc6ae
|
||||
title: Build a Celestial Bodies Database
|
||||
challengeType: 13
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-celestial-bodies-database
|
||||
url: freeCodeCamp/learn-celestial-bodies-database
|
||||
dashedName: build-a-celestial-bodies-database
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 602da04c22201c65d2a019f4
|
||||
title: Build a Number Guessing Game
|
||||
challengeType: 13
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-number-guessing-game
|
||||
url: freeCodeCamp/learn-number-guessing-game
|
||||
dashedName: build-a-number-guessing-game
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 602d9ff222201c65d2a019f2
|
||||
title: Build a Periodic Table Database
|
||||
challengeType: 13
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-periodic-table-database
|
||||
url: freeCodeCamp/learn-periodic-table-database
|
||||
dashedName: build-a-periodic-table-database
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5f87ac112ae598023a42df1a
|
||||
title: Build a Salon Appointment Scheduler
|
||||
challengeType: 13
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-salon-appointment-scheduler
|
||||
url: freeCodeCamp/learn-salon-appointment-scheduler
|
||||
dashedName: build-a-salon-appointment-scheduler
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5f9771307d4d22b9d2b75a94
|
||||
title: Build a World Cup Database
|
||||
challengeType: 13
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-world-cup-database
|
||||
url: freeCodeCamp/learn-world-cup-database
|
||||
dashedName: build-a-world-cup-database
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 602da0de22201c65d2a019f6
|
||||
title: Build a Kitty Ipsum Translator
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-advanced-bash-by-building-a-kitty-ipsum-translator
|
||||
url: freeCodeCamp/learn-advanced-bash-by-building-a-kitty-ipsum-translator
|
||||
dashedName: build-a-kitty-ipsum-translator
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5f5b969a05380d2179fe6e18
|
||||
title: Build a Bike Rental Shop
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-bash-and-sql-by-building-a-bike-rental-shop
|
||||
url: freeCodeCamp/learn-bash-and-sql-by-building-a-bike-rental-shop
|
||||
dashedName: build-a-bike-rental-shop
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5ea8adfab628f68d805bfc5e
|
||||
title: Build a Boilerplate
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-bash-by-building-a-boilerplate
|
||||
url: freeCodeCamp/learn-bash-by-building-a-boilerplate
|
||||
dashedName: build-a-boilerplate
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5f5904ac738bc2fa9efecf5a
|
||||
title: Build Five Programs
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-bash-scripting-by-building-five-programs
|
||||
url: freeCodeCamp/learn-bash-scripting-by-building-five-programs
|
||||
dashedName: build-five-programs
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5fa323cdaf6a73463d590659
|
||||
title: Build an SQL Reference Object
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-git-by-building-an-sql-reference-object
|
||||
url: freeCodeCamp/learn-git-by-building-an-sql-reference-object
|
||||
dashedName: build-an-sql-reference-object
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5f32db63eb37f7e17323f459
|
||||
title: Build a Castle
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-nano-by-building-a-castle
|
||||
url: freeCodeCamp/learn-nano-by-building-a-castle
|
||||
dashedName: build-a-castle
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 5f2c289f164c29556da632fd
|
||||
title: Build a Mario Database
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-relational-databases-by-building-a-mario-database
|
||||
url: freeCodeCamp/learn-relational-databases-by-building-a-mario-database
|
||||
dashedName: build-a-mario-database
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 602da0c222201c65d2a019f5
|
||||
title: "Build a Student Database: Part 1"
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-sql-by-building-a-student-database-part-1
|
||||
url: freeCodeCamp/learn-sql-by-building-a-student-database-part-1
|
||||
dashedName: build-a-student-database-part-1
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ id: 618590adb0730ca724e37672
|
||||
title: "Build a Student Database: Part 2"
|
||||
challengeType: 12
|
||||
helpCategory: Backend Development
|
||||
url: https://github.com/freeCodeCamp/learn-sql-by-building-a-student-database-part-2
|
||||
url: freeCodeCamp/learn-sql-by-building-a-student-database-part-2
|
||||
dashedName: build-a-student-database-part-2
|
||||
---
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ describe('User token widget on settings page,', function () {
|
||||
cy.visit(
|
||||
'/learn/relational-database/learn-bash-by-building-a-boilerplate/build-a-boilerplate'
|
||||
);
|
||||
cy.get('[data-cy=start-codeally]').click();
|
||||
cy.get('[data-cy=codeally-frame]').should('be.visible');
|
||||
cy.contains('Start the course').click();
|
||||
});
|
||||
|
||||
it('should allow you to delete your token', () => {
|
||||
|
||||
Reference in New Issue
Block a user