mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat: save submission to db (#64450)
This commit is contained in:
@@ -2,7 +2,7 @@ import type { CompletedChallenge } from '@prisma/client';
|
|||||||
import validator from 'validator';
|
import validator from 'validator';
|
||||||
import type { FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox';
|
import type { FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox';
|
||||||
|
|
||||||
import { getChallenges } from '../../utils/get-challenges.js';
|
import { challenges, getChallenges } from '../../utils/get-challenges.js';
|
||||||
import {
|
import {
|
||||||
Certification,
|
Certification,
|
||||||
certSlugTypeMap,
|
certSlugTypeMap,
|
||||||
@@ -216,7 +216,6 @@ export const protectedCertificateRoutes: FastifyPluginCallbackTypebox = (
|
|||||||
_options,
|
_options,
|
||||||
done
|
done
|
||||||
) => {
|
) => {
|
||||||
const challenges = getChallenges();
|
|
||||||
const certLookup = createCertLookup(challenges);
|
const certLookup = createCertLookup(challenges);
|
||||||
|
|
||||||
// TODO(POST_MVP): Response should not include updated user. If a client wants the updated user, it should make a separate request
|
// TODO(POST_MVP): Response should not include updated user. If a client wants the updated user, it should make a separate request
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
formatCoderoadChallengeCompletedValidation,
|
formatCoderoadChallengeCompletedValidation,
|
||||||
formatProjectCompletedValidation
|
formatProjectCompletedValidation
|
||||||
} from '../../utils/error-formatting.js';
|
} from '../../utils/error-formatting.js';
|
||||||
import { getChallenges } from '../../utils/get-challenges.js';
|
import { challenges } from '../../utils/get-challenges.js';
|
||||||
import { ProgressTimestamp, getPoints } from '../../utils/progress.js';
|
import { ProgressTimestamp, getPoints } from '../../utils/progress.js';
|
||||||
import {
|
import {
|
||||||
validateExamFromDbSchema,
|
validateExamFromDbSchema,
|
||||||
@@ -57,8 +57,6 @@ const userChallengeSelect = {
|
|||||||
savedChallenges: true
|
savedChallenges: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const challenges = getChallenges();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin for the challenge submission endpoints.
|
* Plugin for the challenge submission endpoints.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { ExamResults, user, Prisma } from '@prisma/client';
|
|||||||
import { FastifyInstance } from 'fastify';
|
import { FastifyInstance } from 'fastify';
|
||||||
import { omit, pick } from 'lodash-es';
|
import { omit, pick } from 'lodash-es';
|
||||||
import { challengeTypes } from '../../../shared/config/challenge-types.js';
|
import { challengeTypes } from '../../../shared/config/challenge-types.js';
|
||||||
import { getChallenges } from './get-challenges.js';
|
import { challenges, savableChallenges } from './get-challenges.js';
|
||||||
import { normalizeDate } from './normalize.js';
|
import { normalizeDate } from './normalize.js';
|
||||||
|
|
||||||
export const jsCertProjectIds = [
|
export const jsCertProjectIds = [
|
||||||
@@ -13,15 +13,15 @@ export const jsCertProjectIds = [
|
|||||||
'aa2e6f85cab2ab736c9a9b24'
|
'aa2e6f85cab2ab736c9a9b24'
|
||||||
];
|
];
|
||||||
|
|
||||||
export const multifileCertProjectIds = getChallenges()
|
export const multifileCertProjectIds = challenges
|
||||||
.filter(c => c.challengeType === challengeTypes.multifileCertProject)
|
.filter(c => c.challengeType === challengeTypes.multifileCertProject)
|
||||||
.map(c => c.id);
|
.map(c => c.id);
|
||||||
|
|
||||||
export const multifilePythonCertProjectIds = getChallenges()
|
export const multifilePythonCertProjectIds = challenges
|
||||||
.filter(c => c.challengeType === challengeTypes.multifilePythonCertProject)
|
.filter(c => c.challengeType === challengeTypes.multifilePythonCertProject)
|
||||||
.map(c => c.id);
|
.map(c => c.id);
|
||||||
|
|
||||||
export const msTrophyChallenges = getChallenges()
|
export const msTrophyChallenges = challenges
|
||||||
.filter(challenge => challenge.challengeType === challengeTypes.msTrophy)
|
.filter(challenge => challenge.challengeType === challengeTypes.msTrophy)
|
||||||
.map(({ id, msTrophyId }) => ({ id, msTrophyId }));
|
.map(({ id, msTrophyId }) => ({ id, msTrophyId }));
|
||||||
|
|
||||||
@@ -133,11 +133,7 @@ export async function updateUserChallengeData(
|
|||||||
_completedChallenge;
|
_completedChallenge;
|
||||||
let completedChallenge: CompletedChallenge;
|
let completedChallenge: CompletedChallenge;
|
||||||
|
|
||||||
if (
|
if (savableChallenges.has(challengeId)) {
|
||||||
jsCertProjectIds.includes(challengeId) ||
|
|
||||||
multifileCertProjectIds.includes(challengeId) ||
|
|
||||||
multifilePythonCertProjectIds.includes(challengeId)
|
|
||||||
) {
|
|
||||||
completedChallenge = {
|
completedChallenge = {
|
||||||
..._completedChallenge,
|
..._completedChallenge,
|
||||||
files: files?.map(
|
files: files?.map(
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ interface Block {
|
|||||||
challengeType: number;
|
challengeType: number;
|
||||||
url?: string;
|
url?: string;
|
||||||
msTrophyId?: string;
|
msTrophyId?: string;
|
||||||
|
saveSubmissionToDB?: boolean;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,3 +52,13 @@ export function getChallenges(): Block['challenges'] {
|
|||||||
return [...acc, ...challengesForBlock.flat()];
|
return [...acc, ...challengesForBlock.flat()];
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const challenges = getChallenges();
|
||||||
|
|
||||||
|
export const savableChallenges = challenges.reduce((acc, curr) => {
|
||||||
|
if (curr.saveSubmissionToDB) {
|
||||||
|
acc.add(curr.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, new Set<string>());
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ exports.createPages = async function createPages({
|
|||||||
history
|
history
|
||||||
fileKey
|
fileKey
|
||||||
}
|
}
|
||||||
|
saveSubmissionToDB
|
||||||
solutions {
|
solutions {
|
||||||
contents
|
contents
|
||||||
ext
|
ext
|
||||||
@@ -334,6 +335,7 @@ exports.createSchemaCustomization = ({ actions }) => {
|
|||||||
questions: [Question]
|
questions: [Question]
|
||||||
quizzes: [Quiz]
|
quizzes: [Quiz]
|
||||||
required: [RequiredResource]
|
required: [RequiredResource]
|
||||||
|
saveSubmissionToDB: Boolean
|
||||||
scene: Scene
|
scene: Scene
|
||||||
solutions: [[FileContents]]
|
solutions: [[FileContents]]
|
||||||
suborder: Int
|
suborder: Int
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ export type ChallengeNode = {
|
|||||||
quizzes: Quiz[];
|
quizzes: Quiz[];
|
||||||
assignments: string[];
|
assignments: string[];
|
||||||
required: Required[];
|
required: Required[];
|
||||||
|
saveSubmissionToDB?: boolean;
|
||||||
scene: FullScene;
|
scene: FullScene;
|
||||||
solutions: {
|
solutions: {
|
||||||
[T: string]: FileKeyChallenge;
|
[T: string]: FileKeyChallenge;
|
||||||
@@ -309,6 +310,7 @@ export type DailyCodingChallengeNode = {
|
|||||||
notes: string;
|
notes: string;
|
||||||
videoUrl?: string;
|
videoUrl?: string;
|
||||||
translationPending: false;
|
translationPending: false;
|
||||||
|
saveSubmissionToDB?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -534,6 +536,7 @@ export type ChallengeMeta = {
|
|||||||
helpCategory: string;
|
helpCategory: string;
|
||||||
disableLoopProtectTests: boolean;
|
disableLoopProtectTests: boolean;
|
||||||
disableLoopProtectPreview: boolean;
|
disableLoopProtectPreview: boolean;
|
||||||
|
saveSubmissionToDB?: boolean;
|
||||||
} & NavigationPaths;
|
} & NavigationPaths;
|
||||||
|
|
||||||
export type NavigationPaths = {
|
export type NavigationPaths = {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { call, put, select, takeEvery } from 'redux-saga/effects';
|
import { call, put, select, takeEvery } from 'redux-saga/effects';
|
||||||
|
|
||||||
import { canSaveToDB } from '../../../shared-dist/config/challenge-types';
|
|
||||||
import { createFlashMessage } from '../components/Flash/redux';
|
import { createFlashMessage } from '../components/Flash/redux';
|
||||||
import { FlashMessages } from '../components/Flash/redux/flash-messages';
|
import { FlashMessages } from '../components/Flash/redux/flash-messages';
|
||||||
import {
|
import {
|
||||||
@@ -19,7 +18,9 @@ import { saveChallengeComplete } from './actions';
|
|||||||
import { savedChallengesSelector } from './selectors';
|
import { savedChallengesSelector } from './selectors';
|
||||||
|
|
||||||
function* saveChallengeSaga() {
|
function* saveChallengeSaga() {
|
||||||
const { id, challengeType } = yield select(challengeMetaSelector);
|
const { id, challengeType, saveSubmissionToDB } = yield select(
|
||||||
|
challengeMetaSelector
|
||||||
|
);
|
||||||
const { challengeFiles } = yield select(challengeDataSelector);
|
const { challengeFiles } = yield select(challengeDataSelector);
|
||||||
const savedChallenges = yield select(savedChallengesSelector);
|
const savedChallenges = yield select(savedChallengesSelector);
|
||||||
const savedChallenge = savedChallenges.find(challenge => challenge.id === id);
|
const savedChallenge = savedChallenges.find(challenge => challenge.id === id);
|
||||||
@@ -34,7 +35,7 @@ function* saveChallengeSaga() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canSaveToDB(challengeType)) {
|
if (saveSubmissionToDB) {
|
||||||
const body = standardizeRequestBody({ id, challengeFiles, challengeType });
|
const body = standardizeRequestBody({ id, challengeFiles, challengeType });
|
||||||
const bodySizeInBytes = getStringSizeInBytes(body);
|
const bodySizeInBytes = getStringSizeInBytes(body);
|
||||||
|
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ import type {
|
|||||||
} from '../../../redux/prop-types';
|
} from '../../../redux/prop-types';
|
||||||
import { editorToneOptions } from '../../../utils/tone/editor-config';
|
import { editorToneOptions } from '../../../utils/tone/editor-config';
|
||||||
import { editorNotes } from '../../../utils/tone/editor-notes';
|
import { editorNotes } from '../../../utils/tone/editor-notes';
|
||||||
import {
|
import { challengeTypes } from '../../../../../shared-dist/config/challenge-types';
|
||||||
canSaveToDB,
|
|
||||||
challengeTypes
|
|
||||||
} from '../../../../../shared-dist/config/challenge-types';
|
|
||||||
import {
|
import {
|
||||||
executeChallenge,
|
executeChallenge,
|
||||||
saveEditorContent,
|
saveEditorContent,
|
||||||
@@ -106,6 +103,7 @@ export interface EditorProps {
|
|||||||
resizeProps: ResizeProps;
|
resizeProps: ResizeProps;
|
||||||
saveChallenge: () => void;
|
saveChallenge: () => void;
|
||||||
saveEditorContent: () => void;
|
saveEditorContent: () => void;
|
||||||
|
saveSubmissionToDB?: boolean;
|
||||||
setEditorFocusability: (isFocusable: boolean) => void;
|
setEditorFocusability: (isFocusable: boolean) => void;
|
||||||
submitChallenge: () => void;
|
submitChallenge: () => void;
|
||||||
stopResetting: () => void;
|
stopResetting: () => void;
|
||||||
@@ -154,7 +152,10 @@ const mapStateToProps = createSelector(
|
|||||||
(
|
(
|
||||||
attempts: number,
|
attempts: number,
|
||||||
canFocus: boolean,
|
canFocus: boolean,
|
||||||
{ challengeType }: { challengeType: number },
|
{
|
||||||
|
challengeType,
|
||||||
|
saveSubmissionToDB
|
||||||
|
}: { challengeType: number; saveSubmissionToDB?: boolean },
|
||||||
open,
|
open,
|
||||||
previewOpen: boolean,
|
previewOpen: boolean,
|
||||||
isResetting: boolean,
|
isResetting: boolean,
|
||||||
@@ -166,6 +167,7 @@ const mapStateToProps = createSelector(
|
|||||||
attempts,
|
attempts,
|
||||||
canFocus: open ? false : canFocus,
|
canFocus: open ? false : canFocus,
|
||||||
challengeType,
|
challengeType,
|
||||||
|
saveSubmissionToDB,
|
||||||
previewOpen,
|
previewOpen,
|
||||||
isResetting,
|
isResetting,
|
||||||
isSignedIn,
|
isSignedIn,
|
||||||
@@ -615,7 +617,7 @@ const Editor = (props: EditorProps): JSX.Element => {
|
|||||||
monaco.KeyMod.WinCtrl | monaco.KeyCode.KeyS
|
monaco.KeyMod.WinCtrl | monaco.KeyCode.KeyS
|
||||||
],
|
],
|
||||||
run:
|
run:
|
||||||
canSaveToDB(props.challengeType) && props.isSignedIn
|
props.saveSubmissionToDB && props.isSignedIn
|
||||||
? // save to database
|
? // save to database
|
||||||
props.saveChallenge
|
props.saveChallenge
|
||||||
: // save to local storage
|
: // save to local storage
|
||||||
|
|||||||
@@ -212,7 +212,8 @@ function ShowClassic({
|
|||||||
usesMultifileEditor,
|
usesMultifileEditor,
|
||||||
notes,
|
notes,
|
||||||
videoUrl,
|
videoUrl,
|
||||||
translationPending
|
translationPending,
|
||||||
|
saveSubmissionToDB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -551,7 +552,10 @@ function ShowClassic({
|
|||||||
superBlock={superBlock}
|
superBlock={superBlock}
|
||||||
/>
|
/>
|
||||||
<VideoModal videoUrl={videoUrl} />
|
<VideoModal videoUrl={videoUrl} />
|
||||||
<ResetModal challengeType={challengeType} challengeTitle={title} />
|
<ResetModal
|
||||||
|
saveSubmissionToDB={saveSubmissionToDB}
|
||||||
|
challengeTitle={title}
|
||||||
|
/>
|
||||||
<ProjectPreviewModal
|
<ProjectPreviewModal
|
||||||
challengeData={challengeData}
|
challengeData={challengeData}
|
||||||
closeText={t('buttons.start-coding')}
|
closeText={t('buttons.start-coding')}
|
||||||
@@ -613,6 +617,7 @@ export const query = graphql`
|
|||||||
editableRegionBoundaries
|
editableRegionBoundaries
|
||||||
history
|
history
|
||||||
}
|
}
|
||||||
|
saveSubmissionToDB
|
||||||
tests {
|
tests {
|
||||||
text
|
text
|
||||||
testString
|
testString
|
||||||
|
|||||||
@@ -8,12 +8,11 @@ import { Button, Modal } from '@freecodecamp/ui';
|
|||||||
import { closeModal, resetChallenge } from '../redux/actions';
|
import { closeModal, resetChallenge } from '../redux/actions';
|
||||||
import { isResetModalOpenSelector } from '../redux/selectors';
|
import { isResetModalOpenSelector } from '../redux/selectors';
|
||||||
import callGA from '../../../analytics/call-ga';
|
import callGA from '../../../analytics/call-ga';
|
||||||
import { canSaveToDB } from '../../../../../shared-dist/config/challenge-types';
|
|
||||||
|
|
||||||
interface ResetModalProps {
|
interface ResetModalProps {
|
||||||
close: () => void;
|
close: () => void;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
challengeType: number;
|
saveSubmissionToDB?: boolean;
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
challengeTitle: string;
|
challengeTitle: string;
|
||||||
}
|
}
|
||||||
@@ -41,7 +40,7 @@ function withActions(...fns: Array<() => void>) {
|
|||||||
function ResetModal({
|
function ResetModal({
|
||||||
reset,
|
reset,
|
||||||
close,
|
close,
|
||||||
challengeType,
|
saveSubmissionToDB,
|
||||||
isOpen,
|
isOpen,
|
||||||
challengeTitle
|
challengeTitle
|
||||||
}: ResetModalProps): JSX.Element {
|
}: ResetModalProps): JSX.Element {
|
||||||
@@ -56,7 +55,7 @@ function ResetModal({
|
|||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body alignment='center'>
|
<Modal.Body alignment='center'>
|
||||||
<p>
|
<p>
|
||||||
{canSaveToDB(challengeType)
|
{saveSubmissionToDB
|
||||||
? t('learn.revert-warn')
|
? t('learn.revert-warn')
|
||||||
: t('learn.reset-warn', {
|
: t('learn.reset-warn', {
|
||||||
title: challengeTitle
|
title: challengeTitle
|
||||||
@@ -73,7 +72,7 @@ function ResetModal({
|
|||||||
variant='danger'
|
variant='danger'
|
||||||
onClick={withActions(reset, close)}
|
onClick={withActions(reset, close)}
|
||||||
>
|
>
|
||||||
{canSaveToDB(challengeType)
|
{saveSubmissionToDB
|
||||||
? t('buttons.revert-to-saved-code')
|
? t('buttons.revert-to-saved-code')
|
||||||
: t('buttons.reset-lesson')}
|
: t('buttons.reset-lesson')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { connect } from 'react-redux';
|
|||||||
import { bindActionCreators, Dispatch } from 'redux';
|
import { bindActionCreators, Dispatch } from 'redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
import { canSaveToDB } from '../../../../../shared-dist/config/challenge-types';
|
|
||||||
import { openModal, executeChallenge } from '../redux/actions';
|
import { openModal, executeChallenge } from '../redux/actions';
|
||||||
import { challengeMetaSelector } from '../redux/selectors';
|
import { challengeMetaSelector } from '../redux/selectors';
|
||||||
import { saveChallenge } from '../../../redux/actions';
|
import { saveChallenge } from '../../../redux/actions';
|
||||||
@@ -18,11 +17,8 @@ import './tool-panel.css';
|
|||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
challengeMetaSelector,
|
challengeMetaSelector,
|
||||||
isSignedInSelector,
|
isSignedInSelector,
|
||||||
(
|
({ saveSubmissionToDB }: { saveSubmissionToDB?: boolean }, isSignedIn) => ({
|
||||||
{ challengeType }: { challengeId: string; challengeType: number },
|
saveSubmissionToDB,
|
||||||
isSignedIn
|
|
||||||
) => ({
|
|
||||||
challengeType,
|
|
||||||
isSignedIn
|
isSignedIn
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -39,7 +35,7 @@ const mapDispatchToProps = (dispatch: Dispatch) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
interface ToolPanelProps {
|
interface ToolPanelProps {
|
||||||
challengeType: number;
|
saveSubmissionToDB?: boolean;
|
||||||
executeChallenge: (options?: { showCompletionModal: boolean }) => void;
|
executeChallenge: (options?: { showCompletionModal: boolean }) => void;
|
||||||
saveChallenge: () => void;
|
saveChallenge: () => void;
|
||||||
isMobile?: boolean;
|
isMobile?: boolean;
|
||||||
@@ -52,7 +48,7 @@ interface ToolPanelProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ToolPanel({
|
function ToolPanel({
|
||||||
challengeType,
|
saveSubmissionToDB,
|
||||||
executeChallenge,
|
executeChallenge,
|
||||||
saveChallenge,
|
saveChallenge,
|
||||||
isMobile,
|
isMobile,
|
||||||
@@ -76,7 +72,7 @@ function ToolPanel({
|
|||||||
<Button block={true} variant='primary' onClick={handleRunTests}>
|
<Button block={true} variant='primary' onClick={handleRunTests}>
|
||||||
{isMobile ? t('buttons.run') : t('buttons.run-test')}
|
{isMobile ? t('buttons.run') : t('buttons.run-test')}
|
||||||
</Button>
|
</Button>
|
||||||
{isSignedIn && canSaveToDB(challengeType) && (
|
{isSignedIn && saveSubmissionToDB && (
|
||||||
<>
|
<>
|
||||||
<Spacer size='xxs' />
|
<Spacer size='xxs' />
|
||||||
<Button block={true} variant='primary' onClick={saveChallenge}>
|
<Button block={true} variant='primary' onClick={saveChallenge}>
|
||||||
@@ -87,9 +83,9 @@ function ToolPanel({
|
|||||||
<Spacer size='xxs' />
|
<Spacer size='xxs' />
|
||||||
<Button block={true} variant='primary' onClick={openResetModal}>
|
<Button block={true} variant='primary' onClick={openResetModal}>
|
||||||
{isMobile
|
{isMobile
|
||||||
? t(canSaveToDB(challengeType) ? 'buttons.revert' : 'buttons.reset')
|
? t(saveSubmissionToDB ? 'buttons.revert' : 'buttons.reset')
|
||||||
: t(
|
: t(
|
||||||
canSaveToDB(challengeType)
|
saveSubmissionToDB
|
||||||
? 'buttons.revert-to-saved-code'
|
? 'buttons.revert-to-saved-code'
|
||||||
: 'buttons.reset-lesson'
|
: 'buttons.reset-lesson'
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
msTrophyVerified
|
msTrophyVerified
|
||||||
} from '../../../utils/error-messages';
|
} from '../../../utils/error-messages';
|
||||||
import {
|
import {
|
||||||
canSaveToDB,
|
|
||||||
challengeTypes,
|
challengeTypes,
|
||||||
getIsDailyCodingChallenge,
|
getIsDailyCodingChallenge,
|
||||||
getDailyCodingChallengeLanguage,
|
getDailyCodingChallengeLanguage,
|
||||||
@@ -119,7 +118,8 @@ function submitModern(type, state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === actionTypes.submitChallenge) {
|
if (type === actionTypes.submitChallenge) {
|
||||||
const { id, block, challengeType } = challengeMetaSelector(state);
|
const { id, challengeType, saveSubmissionToDB } =
|
||||||
|
challengeMetaSelector(state);
|
||||||
|
|
||||||
let update;
|
let update;
|
||||||
|
|
||||||
@@ -140,10 +140,7 @@ function submitModern(type, state) {
|
|||||||
const challengeFiles = challengeFilesSelector(state);
|
const challengeFiles = challengeFilesSelector(state);
|
||||||
|
|
||||||
let body;
|
let body;
|
||||||
if (
|
if (saveSubmissionToDB) {
|
||||||
block === 'javascript-algorithms-and-data-structures-projects' ||
|
|
||||||
canSaveToDB(challengeType)
|
|
||||||
) {
|
|
||||||
body = standardizeRequestBody({ id, challengeType, challengeFiles });
|
body = standardizeRequestBody({ id, challengeType, challengeFiles });
|
||||||
} else {
|
} else {
|
||||||
body = {
|
body = {
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import {
|
|||||||
takeLatest
|
takeLatest
|
||||||
} from 'redux-saga/effects';
|
} from 'redux-saga/effects';
|
||||||
|
|
||||||
import {
|
import { challengeTypes } from '../../../../../shared-dist/config/challenge-types';
|
||||||
canSaveToDB,
|
|
||||||
challengeTypes
|
|
||||||
} from '../../../../../shared-dist/config/challenge-types';
|
|
||||||
import { createFlashMessage } from '../../../components/Flash/redux';
|
import { createFlashMessage } from '../../../components/Flash/redux';
|
||||||
import { FlashMessages } from '../../../components/Flash/redux/flash-messages';
|
import { FlashMessages } from '../../../components/Flash/redux/flash-messages';
|
||||||
import {
|
import {
|
||||||
@@ -77,11 +74,13 @@ const LOGS_TO_IGNORE = [
|
|||||||
|
|
||||||
// when 'run tests' is clicked, do this first
|
// when 'run tests' is clicked, do this first
|
||||||
function* executeCancellableChallengeSaga(payload) {
|
function* executeCancellableChallengeSaga(payload) {
|
||||||
const { challengeType, id } = yield select(challengeMetaSelector);
|
const { challengeType, id, saveSubmissionToDB } = yield select(
|
||||||
|
challengeMetaSelector
|
||||||
|
);
|
||||||
const { challengeFiles } = yield select(challengeDataSelector);
|
const { challengeFiles } = yield select(challengeDataSelector);
|
||||||
|
|
||||||
// if canSaveToDB, see if body/code size is submittable
|
// if canSaveToDB, see if body/code size is submittable
|
||||||
if (canSaveToDB(challengeType)) {
|
if (saveSubmissionToDB) {
|
||||||
const body = standardizeRequestBody({ id, challengeFiles, challengeType });
|
const body = standardizeRequestBody({ id, challengeFiles, challengeType });
|
||||||
const bodySizeInBytes = getStringSizeInBytes(body);
|
const bodySizeInBytes = getStringSizeInBytes(body);
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ const initialState = {
|
|||||||
isLastChallengeInBlock: false,
|
isLastChallengeInBlock: false,
|
||||||
nextChallengePath: '/',
|
nextChallengePath: '/',
|
||||||
prevChallengePath: '/',
|
prevChallengePath: '/',
|
||||||
challengeType: -1
|
challengeType: -1,
|
||||||
|
saveSubmissionToDB: false
|
||||||
},
|
},
|
||||||
challengeTests: [],
|
challengeTests: [],
|
||||||
consoleOut: [],
|
consoleOut: [],
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ exports.createChallengePages = function (
|
|||||||
template,
|
template,
|
||||||
challengeType,
|
challengeType,
|
||||||
id,
|
id,
|
||||||
isLastChallengeInBlock
|
isLastChallengeInBlock,
|
||||||
|
saveSubmissionToDB
|
||||||
} = node.challenge;
|
} = node.challenge;
|
||||||
|
|
||||||
createPage({
|
createPage({
|
||||||
@@ -123,7 +124,8 @@ exports.createChallengePages = function (
|
|||||||
isLastChallengeInBlock: isLastChallengeInBlock,
|
isLastChallengeInBlock: isLastChallengeInBlock,
|
||||||
nextChallengePath: idToNextPathCurrentCurriculum[node.id],
|
nextChallengePath: idToNextPathCurrentCurriculum[node.id],
|
||||||
prevChallengePath: idToPrevPathCurrentCurriculum[node.id],
|
prevChallengePath: idToPrevPathCurrentCurriculum[node.id],
|
||||||
id
|
id,
|
||||||
|
saveSubmissionToDB
|
||||||
},
|
},
|
||||||
projectPreview: getProjectPreviewConfig(
|
projectPreview: getProjectPreviewConfig(
|
||||||
node.challenge,
|
node.challenge,
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 5e44413e903586ffb414c94e
|
id: 5e44413e903586ffb414c94e
|
||||||
title: Build a Budget App Project
|
title: Build a Budget App Project
|
||||||
challengeType: 23
|
challengeType: 23
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 462361
|
forumTopicId: 462361
|
||||||
dashedName: build-a-budget-app-project
|
dashedName: build-a-budget-app-project
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 657bdcc3a322aae1eac38392
|
id: 657bdcc3a322aae1eac38392
|
||||||
title: Build a Cash Register
|
title: Build a Cash Register
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16012
|
forumTopicId: 16012
|
||||||
dashedName: build-a-cash-register
|
dashedName: build-a-cash-register
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 657bdc55a322aae1eac3838f
|
id: 657bdc55a322aae1eac3838f
|
||||||
title: Build a Palindrome Checker
|
title: Build a Palindrome Checker
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16004
|
forumTopicId: 16004
|
||||||
dashedName: build-a-palindrome-checker
|
dashedName: build-a-palindrome-checker
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: bd7158d8c242eddfaeb5bd13
|
id: bd7158d8c242eddfaeb5bd13
|
||||||
title: Build a Personal Portfolio Webpage
|
title: Build a Personal Portfolio Webpage
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 301143
|
forumTopicId: 301143
|
||||||
dashedName: build-a-personal-portfolio-webpage
|
dashedName: build-a-personal-portfolio-webpage
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 5e444147903586ffb414c94f
|
id: 5e444147903586ffb414c94f
|
||||||
title: Build a Polygon Area Calculator Project
|
title: Build a Polygon Area Calculator Project
|
||||||
challengeType: 23
|
challengeType: 23
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 462363
|
forumTopicId: 462363
|
||||||
dashedName: build-a-polygon-area-calculator-project
|
dashedName: build-a-polygon-area-calculator-project
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 5e44414f903586ffb414c950
|
id: 5e44414f903586ffb414c950
|
||||||
title: Build a Probability Calculator Project
|
title: Build a Probability Calculator Project
|
||||||
challengeType: 23
|
challengeType: 23
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 462364
|
forumTopicId: 462364
|
||||||
dashedName: build-a-probability-calculator-project
|
dashedName: build-a-probability-calculator-project
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 587d78af367417b2b2512b04
|
id: 587d78af367417b2b2512b04
|
||||||
title: Build a Product Landing Page
|
title: Build a Product Landing Page
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 301144
|
forumTopicId: 301144
|
||||||
dashedName: build-a-product-landing-page
|
dashedName: build-a-product-landing-page
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 657bdc8ba322aae1eac38390
|
id: 657bdc8ba322aae1eac38390
|
||||||
title: Build a Roman Numeral Converter
|
title: Build a Roman Numeral Converter
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16044
|
forumTopicId: 16044
|
||||||
dashedName: build-a-roman-numeral-converter
|
dashedName: build-a-roman-numeral-converter
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 587d78af367417b2b2512b03
|
id: 587d78af367417b2b2512b03
|
||||||
title: Build a Survey Form
|
title: Build a Survey Form
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 301145
|
forumTopicId: 301145
|
||||||
dashedName: build-a-survey-form
|
dashedName: build-a-survey-form
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 587d78b0367417b2b2512b05
|
id: 587d78b0367417b2b2512b05
|
||||||
title: Build a Technical Documentation Page
|
title: Build a Technical Documentation Page
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 301146
|
forumTopicId: 301146
|
||||||
dashedName: build-a-technical-documentation-page
|
dashedName: build-a-technical-documentation-page
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 657bdcb9a322aae1eac38391
|
id: 657bdcb9a322aae1eac38391
|
||||||
title: Build a Telephone Number Validator
|
title: Build a Telephone Number Validator
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16090
|
forumTopicId: 16090
|
||||||
dashedName: build-a-telephone-number-validator
|
dashedName: build-a-telephone-number-validator
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 5e444136903586ffb414c94d
|
id: 5e444136903586ffb414c94d
|
||||||
title: Build a Time Calculator Project
|
title: Build a Time Calculator Project
|
||||||
challengeType: 23
|
challengeType: 23
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 462360
|
forumTopicId: 462360
|
||||||
dashedName: build-a-time-calculator-project
|
dashedName: build-a-time-calculator-project
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: bd7158d8c442eddfaeb5bd18
|
id: bd7158d8c442eddfaeb5bd18
|
||||||
title: Build a Tribute Page
|
title: Build a Tribute Page
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 301147
|
forumTopicId: 301147
|
||||||
dashedName: build-a-tribute-page
|
dashedName: build-a-tribute-page
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 5e44412c903586ffb414c94c
|
id: 5e44412c903586ffb414c94c
|
||||||
title: Build an Arithmetic Formatter Project
|
title: Build an Arithmetic Formatter Project
|
||||||
challengeType: 23
|
challengeType: 23
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 462359
|
forumTopicId: 462359
|
||||||
dashedName: build-an-arithmetic-formatter-project
|
dashedName: build-an-arithmetic-formatter-project
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 6555c1d3e11a1574434cf8b5
|
id: 6555c1d3e11a1574434cf8b5
|
||||||
title: Build an RPG Creature Search App
|
title: Build an RPG Creature Search App
|
||||||
challengeType: 14
|
challengeType: 14
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16003
|
forumTopicId: 16003
|
||||||
dashedName: build-an-rpg-creature-search-app
|
dashedName: build-an-rpg-creature-search-app
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: 56533eb9ac21ba0edf2244e2
|
id: 56533eb9ac21ba0edf2244e2
|
||||||
title: Caesars Cipher
|
title: Caesars Cipher
|
||||||
challengeType: 5
|
challengeType: 5
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16003
|
forumTopicId: 16003
|
||||||
dashedName: caesars-cipher
|
dashedName: caesars-cipher
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: a7f4d8f2483413a6ce226cac
|
id: a7f4d8f2483413a6ce226cac
|
||||||
title: Roman Numeral Converter
|
title: Roman Numeral Converter
|
||||||
challengeType: 5
|
challengeType: 5
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16044
|
forumTopicId: 16044
|
||||||
dashedName: roman-numeral-converter
|
dashedName: roman-numeral-converter
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: aa2e6f85cab2ab736c9a9b24
|
id: aa2e6f85cab2ab736c9a9b24
|
||||||
title: Cash Register
|
title: Cash Register
|
||||||
challengeType: 5
|
challengeType: 5
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16012
|
forumTopicId: 16012
|
||||||
dashedName: cash-register
|
dashedName: cash-register
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: aaa48de84e1ecc7c742e1124
|
id: aaa48de84e1ecc7c742e1124
|
||||||
title: Palindrome Checker
|
title: Palindrome Checker
|
||||||
challengeType: 5
|
challengeType: 5
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16004
|
forumTopicId: 16004
|
||||||
dashedName: palindrome-checker
|
dashedName: palindrome-checker
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
id: aff0395860f5d3034dc0bfc9
|
id: aff0395860f5d3034dc0bfc9
|
||||||
title: Telephone Number Validator
|
title: Telephone Number Validator
|
||||||
challengeType: 5
|
challengeType: 5
|
||||||
|
saveSubmissionToDB: true
|
||||||
forumTopicId: 16090
|
forumTopicId: 16090
|
||||||
dashedName: telephone-number-validator
|
dashedName: telephone-number-validator
|
||||||
---
|
---
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ id: 6718d2d59337c822ecb697ff
|
|||||||
title: Build a Bank Account Management Program
|
title: Build a Bank Account Management Program
|
||||||
challengeType: 26
|
challengeType: 26
|
||||||
dashedName: build-a-bank-account-management-program
|
dashedName: build-a-bank-account-management-program
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Book Inventory App
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-book-inventory-app
|
dashedName: build-a-book-inventory-app
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ id: 5e44413e903586ffb414c94e
|
|||||||
title: Build a Budget App
|
title: Build a Budget App
|
||||||
challengeType: 27
|
challengeType: 27
|
||||||
dashedName: build-a-budget-app
|
dashedName: build-a-budget-app
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Celestial Bodies Database
|
|||||||
challengeType: 13
|
challengeType: 13
|
||||||
url: freeCodeCamp/learn-celestial-bodies-database
|
url: freeCodeCamp/learn-celestial-bodies-database
|
||||||
dashedName: lab-celestial-bodies-database
|
dashedName: lab-celestial-bodies-database
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Currency Converter
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-currency-converter
|
dashedName: build-a-currency-converter
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ title: Build a Drum Machine
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-drum-machine
|
dashedName: build-drum-machine
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ id: 67ed03ac474c48692f41749e
|
|||||||
title: Build a Hash Table
|
title: Build a Hash Table
|
||||||
challengeType: 27
|
challengeType: 27
|
||||||
dashedName: build-a-hash-table
|
dashedName: build-a-hash-table
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Markdown to HTML Converter
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-markdown-to-html-converter
|
dashedName: build-a-markdown-to-html-converter
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Number Guessing Game
|
|||||||
challengeType: 13
|
challengeType: 13
|
||||||
url: freeCodeCamp/learn-number-guessing-game
|
url: freeCodeCamp/learn-number-guessing-game
|
||||||
dashedName: lab-number-guessing-game
|
dashedName: lab-number-guessing-game
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Page of Playing Cards
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-page-of-playing-cards
|
dashedName: build-a-page-of-playing-cards
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Palindrome Checker
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-palindrome-checker
|
dashedName: build-a-palindrome-checker
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Periodic Table Database
|
|||||||
challengeType: 13
|
challengeType: 13
|
||||||
url: freeCodeCamp/learn-periodic-table-database
|
url: freeCodeCamp/learn-periodic-table-database
|
||||||
dashedName: lab-periodic-table-database
|
dashedName: lab-periodic-table-database
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Personal Portfolio
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-personal-portfolio
|
dashedName: build-a-personal-portfolio
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ id: 5e444147903586ffb414c94f
|
|||||||
title: Build a Polygon Area Calculator
|
title: Build a Polygon Area Calculator
|
||||||
challengeType: 27
|
challengeType: 27
|
||||||
dashedName: build-a-polygon-area-calculator
|
dashedName: build-a-polygon-area-calculator
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Product Landing Page
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-product-landing-page
|
dashedName: build-a-product-landing-page
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Salon Appointment Scheduler
|
|||||||
challengeType: 13
|
challengeType: 13
|
||||||
url: freeCodeCamp/learn-salon-appointment-scheduler
|
url: freeCodeCamp/learn-salon-appointment-scheduler
|
||||||
dashedName: lab-salon-appointment-scheduler
|
dashedName: lab-salon-appointment-scheduler
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ title: Build a Survey Form
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-survey-form
|
dashedName: build-a-survey-form
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a Technical Documentation Page
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
dashedName: build-a-technical-documentation-page
|
dashedName: build-a-technical-documentation-page
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ title: Build a Tic-Tac-Toe Game
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: build-a-tic-tac-toe-game
|
dashedName: build-a-tic-tac-toe-game
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
id: 68773ee26f332a80bc0295db
|
id: 68773ee26f332a80bc0295db
|
||||||
title: Implement the Tower of Hanoi Algorithm
|
title: Implement the Tower of Hanoi Algorithm
|
||||||
challengeType: 23
|
challengeType: 23
|
||||||
|
saveSubmissionToDB: true
|
||||||
dashedName: implement-the-tower-of-hanoi-algorithm
|
dashedName: implement-the-tower-of-hanoi-algorithm
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ title: Build a Tribute Page
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
dashedName: build-a-tribute-page
|
dashedName: build-a-tribute-page
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -3,6 +3,7 @@ id: 684aaf9ec670c68d20efd0d0
|
|||||||
title: Build a User Configuration Manager
|
title: Build a User Configuration Manager
|
||||||
challengeType: 27
|
challengeType: 27
|
||||||
dashedName: build-a-user-configuration-manager
|
dashedName: build-a-user-configuration-manager
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ id: 673b567e3ba535dda140d278
|
|||||||
title: Build a Voting System
|
title: Build a Voting System
|
||||||
challengeType: 26
|
challengeType: 26
|
||||||
dashedName: build-a-voting-system
|
dashedName: build-a-voting-system
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ title: Build a Weather App
|
|||||||
challengeType: 25
|
challengeType: 25
|
||||||
dashedName: lab-weather-app
|
dashedName: lab-weather-app
|
||||||
demoType: onClick
|
demoType: onClick
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@ title: Build a World Cup Database
|
|||||||
challengeType: 13
|
challengeType: 13
|
||||||
url: freeCodeCamp/learn-world-cup-database
|
url: freeCodeCamp/learn-world-cup-database
|
||||||
dashedName: lab-world-cup-database
|
dashedName: lab-world-cup-database
|
||||||
|
saveSubmissionToDB: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ const schema = Joi.object().keys({
|
|||||||
then: Joi.array().items(Joi.string()).required(),
|
then: Joi.array().items(Joi.string()).required(),
|
||||||
otherwise: Joi.array().items(Joi.string())
|
otherwise: Joi.array().items(Joi.string())
|
||||||
}),
|
}),
|
||||||
|
saveSubmissionToDB: Joi.bool(),
|
||||||
scene: Joi.object().keys({
|
scene: Joi.object().keys({
|
||||||
setup: setupJoi.required(),
|
setup: setupJoi.required(),
|
||||||
commands: Joi.array()
|
commands: Joi.array()
|
||||||
|
|||||||
@@ -170,10 +170,6 @@ export const submitTypes = {
|
|||||||
[review]: 'tests'
|
[review]: 'tests'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const canSaveToDB = (challengeType: number): boolean =>
|
|
||||||
challengeType === challengeTypes.multifileCertProject ||
|
|
||||||
challengeType === challengeTypes.multifilePythonCertProject;
|
|
||||||
|
|
||||||
const dailyCodingChallengeTypes = [
|
const dailyCodingChallengeTypes = [
|
||||||
challengeTypes.dailyChallengeJs,
|
challengeTypes.dailyChallengeJs,
|
||||||
challengeTypes.dailyChallengePy
|
challengeTypes.dailyChallengePy
|
||||||
|
|||||||
Reference in New Issue
Block a user