feat(api): get challenges directly from /curriculum
This commit is contained in:
@@ -31,20 +31,25 @@ import { oldDataVizId } from '../../../config/misc';
|
||||
import certTypes from '../utils/certTypes.json';
|
||||
import superBlockCertTypeMap from '../utils/superBlockCertTypeMap';
|
||||
import { completeCommitment$ } from '../utils/commit';
|
||||
import { getChallenges } from '../utils/get-curriculum';
|
||||
|
||||
const log = debug('fcc:certification');
|
||||
|
||||
export default function bootCertificate(app) {
|
||||
export default function bootCertificate(app, done) {
|
||||
const api = app.loopback.Router();
|
||||
// TODO: rather than getting all the challenges, then grabbing the certs,
|
||||
// consider just getting the certs.
|
||||
getChallenges().then(allChallenges => {
|
||||
const certTypeIds = createCertTypeIds(allChallenges);
|
||||
const showCert = createShowCert(app);
|
||||
const verifyCert = createVerifyCert(certTypeIds, app);
|
||||
|
||||
const certTypeIds = createCertTypeIds(app);
|
||||
const showCert = createShowCert(app);
|
||||
const verifyCert = createVerifyCert(certTypeIds, app);
|
||||
api.put('/certificate/verify', ifNoUser401, ifNoSuperBlock404, verifyCert);
|
||||
api.get('/certificate/showCert/:username/:cert', showCert);
|
||||
|
||||
api.put('/certificate/verify', ifNoUser401, ifNoSuperBlock404, verifyCert);
|
||||
api.get('/certificate/showCert/:username/:cert', showCert);
|
||||
|
||||
app.use(api);
|
||||
app.use(api);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
export function getFallbackFrontEndDate(completedChallenges, completedDate) {
|
||||
@@ -97,33 +102,37 @@ const renderCertifiedEmail = loopback.template(
|
||||
path.join(__dirname, '..', 'views', 'emails', 'certified.ejs')
|
||||
);
|
||||
|
||||
function createCertTypeIds(app) {
|
||||
const { Challenge } = app.models;
|
||||
|
||||
function createCertTypeIds(allChallenges) {
|
||||
return {
|
||||
// legacy
|
||||
[certTypes.frontEnd]: getIdsForCert$(legacyFrontEndChallengeId, Challenge),
|
||||
[certTypes.backEnd]: getIdsForCert$(legacyBackEndChallengeId, Challenge),
|
||||
[certTypes.dataVis]: getIdsForCert$(legacyDataVisId, Challenge),
|
||||
[certTypes.infosecQa]: getIdsForCert$(legacyInfosecQaId, Challenge),
|
||||
[certTypes.fullStack]: getIdsForCert$(legacyFullStackId, Challenge),
|
||||
[certTypes.frontEnd]: getCertById(legacyFrontEndChallengeId, allChallenges),
|
||||
[certTypes.backEnd]: getCertById(legacyBackEndChallengeId, allChallenges),
|
||||
[certTypes.dataVis]: getCertById(legacyDataVisId, allChallenges),
|
||||
[certTypes.infosecQa]: getCertById(legacyInfosecQaId, allChallenges),
|
||||
[certTypes.fullStack]: getCertById(legacyFullStackId, allChallenges),
|
||||
|
||||
// modern
|
||||
[certTypes.respWebDesign]: getIdsForCert$(respWebDesignId, Challenge),
|
||||
[certTypes.frontEndLibs]: getIdsForCert$(frontEndLibsId, Challenge),
|
||||
[certTypes.dataVis2018]: getIdsForCert$(dataVis2018Id, Challenge),
|
||||
[certTypes.jsAlgoDataStruct]: getIdsForCert$(jsAlgoDataStructId, Challenge),
|
||||
[certTypes.apisMicroservices]: getIdsForCert$(
|
||||
apisMicroservicesId,
|
||||
Challenge
|
||||
[certTypes.respWebDesign]: getCertById(respWebDesignId, allChallenges),
|
||||
[certTypes.frontEndLibs]: getCertById(frontEndLibsId, allChallenges),
|
||||
[certTypes.dataVis2018]: getCertById(dataVis2018Id, allChallenges),
|
||||
[certTypes.jsAlgoDataStruct]: getCertById(
|
||||
jsAlgoDataStructId,
|
||||
allChallenges
|
||||
),
|
||||
[certTypes.qaV7]: getIdsForCert$(qaV7Id, Challenge),
|
||||
[certTypes.infosecV7]: getIdsForCert$(infosecV7Id, Challenge),
|
||||
[certTypes.sciCompPyV7]: getIdsForCert$(sciCompPyV7Id, Challenge),
|
||||
[certTypes.dataAnalysisPyV7]: getIdsForCert$(dataAnalysisPyV7Id, Challenge),
|
||||
[certTypes.machineLearningPyV7]: getIdsForCert$(
|
||||
[certTypes.apisMicroservices]: getCertById(
|
||||
apisMicroservicesId,
|
||||
allChallenges
|
||||
),
|
||||
[certTypes.qaV7]: getCertById(qaV7Id, allChallenges),
|
||||
[certTypes.infosecV7]: getCertById(infosecV7Id, allChallenges),
|
||||
[certTypes.sciCompPyV7]: getCertById(sciCompPyV7Id, allChallenges),
|
||||
[certTypes.dataAnalysisPyV7]: getCertById(
|
||||
dataAnalysisPyV7Id,
|
||||
allChallenges
|
||||
),
|
||||
[certTypes.machineLearningPyV7]: getCertById(
|
||||
machineLearningPyV7Id,
|
||||
Challenge
|
||||
allChallenges
|
||||
)
|
||||
};
|
||||
}
|
||||
@@ -188,13 +197,16 @@ const completionHours = {
|
||||
[certTypes.machineLearningPyV7]: 400
|
||||
};
|
||||
|
||||
function getIdsForCert$(id, Challenge) {
|
||||
return observeQuery(Challenge, 'findById', id, {
|
||||
id: true,
|
||||
tests: true,
|
||||
name: true,
|
||||
challengeType: true
|
||||
}).shareReplay();
|
||||
// returns an array with a single element, to be flatMap'd by createdVerifyCert
|
||||
function getCertById(anId, allChallenges) {
|
||||
return allChallenges
|
||||
.filter(({ id }) => id === anId)
|
||||
.map(({ id, tests, name, challengeType }) => ({
|
||||
id,
|
||||
tests,
|
||||
name,
|
||||
challengeType
|
||||
}));
|
||||
}
|
||||
|
||||
const superBlocks = Object.keys(superBlockCertTypeMap);
|
||||
|
@@ -18,6 +18,7 @@ import { ifNoUserSend } from '../utils/middleware';
|
||||
import { dasherize } from '../../../utils/slugs';
|
||||
import _pathMigrations from '../resources/pathMigration.json';
|
||||
import { fixCompletedChallengeItem } from '../../common/utils';
|
||||
import { getChallenges } from '../utils/get-curriculum';
|
||||
|
||||
const log = debug('fcc:boot:challenges');
|
||||
|
||||
@@ -26,7 +27,9 @@ export default async function bootChallenge(app, done) {
|
||||
const api = app.loopback.Router();
|
||||
const router = app.loopback.Router();
|
||||
const redirectToLearn = createRedirectToLearn(_pathMigrations);
|
||||
const challengeUrlResolver = await createChallengeUrlResolver(app);
|
||||
const challengeUrlResolver = await createChallengeUrlResolver(
|
||||
await getChallenges()
|
||||
);
|
||||
const redirectToCurrentChallenge = createRedirectToCurrentChallenge(
|
||||
challengeUrlResolver
|
||||
);
|
||||
@@ -148,44 +151,46 @@ export function buildChallengeUrl(challenge) {
|
||||
return `/learn/${dasherize(superBlock)}/${dasherize(block)}/${dashedName}`;
|
||||
}
|
||||
|
||||
export function getFirstChallenge(Challenge) {
|
||||
return new Promise(resolve => {
|
||||
Challenge.findOne(
|
||||
{ where: { challengeOrder: 0, superOrder: 1, order: 0 } },
|
||||
(err, challenge) => {
|
||||
if (err || isEmpty(challenge)) {
|
||||
return resolve('/learn');
|
||||
}
|
||||
return resolve(buildChallengeUrl(challenge));
|
||||
}
|
||||
);
|
||||
});
|
||||
// this is only called once during boot, so it can be slow.
|
||||
export function getFirstChallenge(allChallenges) {
|
||||
const first = allChallenges.find(
|
||||
({ challengeOrder, superOrder, order }) =>
|
||||
challengeOrder === 0 && superOrder === 1 && order === 0
|
||||
);
|
||||
|
||||
return first ? buildChallengeUrl(first) : '/learn';
|
||||
}
|
||||
|
||||
function getChallengeById(allChallenges, targetId) {
|
||||
return allChallenges.find(({ id }) => id === targetId);
|
||||
}
|
||||
|
||||
export async function createChallengeUrlResolver(
|
||||
app,
|
||||
allChallenges,
|
||||
{ _getFirstChallenge = getFirstChallenge } = {}
|
||||
) {
|
||||
const { Challenge } = app.models;
|
||||
const cache = new Map();
|
||||
const firstChallenge = await _getFirstChallenge(Challenge);
|
||||
const firstChallenge = _getFirstChallenge(allChallenges);
|
||||
|
||||
return function resolveChallengeUrl(id) {
|
||||
if (isEmpty(id)) {
|
||||
return Promise.resolve(firstChallenge);
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
if (cache.has(id)) {
|
||||
return resolve(cache.get(id));
|
||||
}
|
||||
return Challenge.findById(id, (err, challenge) => {
|
||||
if (err || isEmpty(challenge)) {
|
||||
return resolve(firstChallenge);
|
||||
} else {
|
||||
return new Promise(resolve => {
|
||||
if (cache.has(id)) {
|
||||
resolve(cache.get(id));
|
||||
}
|
||||
|
||||
const challenge = getChallengeById(allChallenges, id);
|
||||
if (isEmpty(challenge)) {
|
||||
resolve(firstChallenge);
|
||||
} else {
|
||||
const challengeUrl = buildChallengeUrl(challenge);
|
||||
cache.set(id, challengeUrl);
|
||||
resolve(challengeUrl);
|
||||
}
|
||||
const challengeUrl = buildChallengeUrl(challenge);
|
||||
cache.set(id, challengeUrl);
|
||||
return resolve(challengeUrl);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user