chore(deps): update dependency prettier to v2.3.0 (#42074)
* chore(deps): update dependency prettier to v2.3.0 * chore: apply formating per prettier * fix: correctly disable import/no-unresolved Co-authored-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: Mrugesh Mohapatra <hi@mrugesh.dev> Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@ -676,10 +676,8 @@ export default function initializeUser(User) {
|
|||||||
const updateData = { $set: {} };
|
const updateData = { $set: {} };
|
||||||
return this.getCompletedChallenges$()
|
return this.getCompletedChallenges$()
|
||||||
.flatMap(() => {
|
.flatMap(() => {
|
||||||
const {
|
const { updated, isNewCompletionCount } =
|
||||||
updated,
|
buildCompletedChallengesUpdate(this.completedChallenges, project);
|
||||||
isNewCompletionCount
|
|
||||||
} = buildCompletedChallengesUpdate(this.completedChallenges, project);
|
|
||||||
updateData.$set.completedChallenges = updated;
|
updateData.$set.completedChallenges = updated;
|
||||||
if (isNewCompletionCount) {
|
if (isNewCompletionCount) {
|
||||||
let points = [];
|
let points = [];
|
||||||
@ -830,12 +828,8 @@ export default function initializeUser(User) {
|
|||||||
if (!user) {
|
if (!user) {
|
||||||
return Observable.of({});
|
return Observable.of({});
|
||||||
}
|
}
|
||||||
const {
|
const { completedChallenges, progressTimestamps, timezone, profileUI } =
|
||||||
completedChallenges,
|
user;
|
||||||
progressTimestamps,
|
|
||||||
timezone,
|
|
||||||
profileUI
|
|
||||||
} = user;
|
|
||||||
const allUser = {
|
const allUser = {
|
||||||
..._.pick(user, publicUserProps),
|
..._.pick(user, publicUserProps),
|
||||||
isGithub: !!user.githubProfile,
|
isGithub: !!user.githubProfile,
|
||||||
|
@ -97,57 +97,54 @@ export const devLoginRedirect = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createPassportCallbackAuthenticator = (strategy, config) => (
|
export const createPassportCallbackAuthenticator =
|
||||||
req,
|
(strategy, config) => (req, res, next) => {
|
||||||
res,
|
return passport.authenticate(
|
||||||
next
|
strategy,
|
||||||
) => {
|
{ session: false },
|
||||||
return passport.authenticate(
|
(err, user, userInfo) => {
|
||||||
strategy,
|
if (err) {
|
||||||
{ session: false },
|
return next(err);
|
||||||
(err, user, userInfo) => {
|
}
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user || !userInfo) {
|
if (!user || !userInfo) {
|
||||||
return res.redirect('/signin');
|
return res.redirect('/signin');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { accessToken } = userInfo;
|
const { accessToken } = userInfo;
|
||||||
const { provider } = config;
|
const { provider } = config;
|
||||||
if (accessToken && accessToken.id) {
|
if (accessToken && accessToken.id) {
|
||||||
if (provider === 'auth0') {
|
if (provider === 'auth0') {
|
||||||
req.flash('success', 'flash.signin-success');
|
req.flash('success', 'flash.signin-success');
|
||||||
} else if (user.email) {
|
} else if (user.email) {
|
||||||
req.flash(
|
req.flash(
|
||||||
'info',
|
'info',
|
||||||
dedent`
|
dedent`
|
||||||
We are moving away from social authentication for privacy reasons. Next time
|
We are moving away from social authentication for privacy reasons. Next time
|
||||||
we recommend using your email address: ${user.email} to sign in instead.
|
we recommend using your email address: ${user.email} to sign in instead.
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
setAccessTokenToResponse({ accessToken }, req, res);
|
||||||
|
req.login(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = req && req.query && req.query.state;
|
||||||
|
// returnTo, origin and pathPrefix are audited by getReturnTo
|
||||||
|
let { returnTo, origin, pathPrefix } = getReturnTo(state, jwtSecret);
|
||||||
|
const redirectBase = getRedirectBase(origin, pathPrefix);
|
||||||
|
|
||||||
|
// TODO: getReturnTo could return a success flag to show a flash message,
|
||||||
|
// but currently it immediately gets overwritten by a second message. We
|
||||||
|
// should either change the message if the flag is present or allow
|
||||||
|
// multiple messages to appear at once.
|
||||||
|
|
||||||
|
if (user.acceptedPrivacyTerms) {
|
||||||
|
returnTo += isRootPath(redirectBase, returnTo) ? '/learn' : '';
|
||||||
|
return res.redirectWithFlash(returnTo);
|
||||||
|
} else {
|
||||||
|
return res.redirectWithFlash(`${redirectBase}/email-sign-up`);
|
||||||
}
|
}
|
||||||
setAccessTokenToResponse({ accessToken }, req, res);
|
|
||||||
req.login(user);
|
|
||||||
}
|
}
|
||||||
|
)(req, res, next);
|
||||||
const state = req && req.query && req.query.state;
|
};
|
||||||
// returnTo, origin and pathPrefix are audited by getReturnTo
|
|
||||||
let { returnTo, origin, pathPrefix } = getReturnTo(state, jwtSecret);
|
|
||||||
const redirectBase = getRedirectBase(origin, pathPrefix);
|
|
||||||
|
|
||||||
// TODO: getReturnTo could return a success flag to show a flash message,
|
|
||||||
// but currently it immediately gets overwritten by a second message. We
|
|
||||||
// should either change the message if the flag is present or allow
|
|
||||||
// multiple messages to appear at once.
|
|
||||||
|
|
||||||
if (user.acceptedPrivacyTerms) {
|
|
||||||
returnTo += isRootPath(redirectBase, returnTo) ? '/learn' : '';
|
|
||||||
return res.redirectWithFlash(returnTo);
|
|
||||||
} else {
|
|
||||||
return res.redirectWithFlash(`${redirectBase}/email-sign-up`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)(req, res, next);
|
|
||||||
};
|
|
||||||
|
@ -53,14 +53,12 @@ export const mockCancellationHook = {
|
|||||||
},
|
},
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1VF24938EU372274X-83540367M0110254R',
|
||||||
'https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1VF24938EU372274X-83540367M0110254R',
|
|
||||||
rel: 'self',
|
rel: 'self',
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1VF24938EU372274X-83540367M0110254R/resend',
|
||||||
'https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1VF24938EU372274X-83540367M0110254R/resend',
|
|
||||||
rel: 'resend',
|
rel: 'resend',
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}
|
}
|
||||||
@ -156,32 +154,27 @@ export const mockActivationHook = {
|
|||||||
},
|
},
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G',
|
||||||
'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G',
|
|
||||||
rel: 'self',
|
rel: 'self',
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G',
|
||||||
'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G',
|
|
||||||
rel: 'edit',
|
rel: 'edit',
|
||||||
method: 'PATCH'
|
method: 'PATCH'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G/suspend',
|
||||||
'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G/suspend',
|
|
||||||
rel: 'suspend',
|
rel: 'suspend',
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G/cancel',
|
||||||
'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G/cancel',
|
|
||||||
rel: 'cancel',
|
rel: 'cancel',
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G/capture',
|
||||||
'https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G/capture',
|
|
||||||
rel: 'capture',
|
rel: 'capture',
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}
|
}
|
||||||
@ -194,15 +187,13 @@ export const mockActivationHook = {
|
|||||||
},
|
},
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.paypal.com/v1/notifications/webhooks-events/WH-77687562XN25889J8-8Y6T55435R66168T6',
|
||||||
'https://api.paypal.com/v1/notifications/webhooks-events/WH-77687562XN25889J8-8Y6T55435R66168T6',
|
|
||||||
rel: 'self',
|
rel: 'self',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
encType: 'application/json'
|
encType: 'application/json'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href:
|
href: 'https://api.paypal.com/v1/notifications/webhooks-events/WH-77687562XN25889J8-8Y6T55435R66168T6/resend',
|
||||||
'https://api.paypal.com/v1/notifications/webhooks-events/WH-77687562XN25889J8-8Y6T55435R66168T6/resend',
|
|
||||||
rel: 'resend',
|
rel: 'resend',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
encType: 'application/json'
|
encType: 'application/json'
|
||||||
|
@ -17,11 +17,13 @@ export function wrapHandledError(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for use with express-validator error formatter
|
// for use with express-validator error formatter
|
||||||
export const createValidatorErrorFormatter = (type, redirectTo) => ({ msg }) =>
|
export const createValidatorErrorFormatter =
|
||||||
wrapHandledError(new Error(msg), {
|
(type, redirectTo) =>
|
||||||
type,
|
({ msg }) =>
|
||||||
message: msg,
|
wrapHandledError(new Error(msg), {
|
||||||
redirectTo,
|
type,
|
||||||
// we default to 400 as these are malformed requests
|
message: msg,
|
||||||
status: 400
|
redirectTo,
|
||||||
});
|
// we default to 400 as these are malformed requests
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
@ -24,10 +24,8 @@ jest.mock('axios');
|
|||||||
|
|
||||||
const verificationUrl = `https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature`;
|
const verificationUrl = `https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature`;
|
||||||
const tokenUrl = `https://api.sandbox.paypal.com/v1/oauth2/token`;
|
const tokenUrl = `https://api.sandbox.paypal.com/v1/oauth2/token`;
|
||||||
const {
|
const { body: activationHookBody, headers: activationHookHeaders } =
|
||||||
body: activationHookBody,
|
mockActivationHook;
|
||||||
headers: activationHookHeaders
|
|
||||||
} = mockActivationHook;
|
|
||||||
|
|
||||||
describe('donation', () => {
|
describe('donation', () => {
|
||||||
describe('getAsyncPaypalToken', () => {
|
describe('getAsyncPaypalToken', () => {
|
||||||
|
@ -78,15 +78,17 @@ export function ifUserRedirectTo(status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for use with express-validator error formatter
|
// for use with express-validator error formatter
|
||||||
export const createValidatorErrorHandler = (...args) => (req, res, next) => {
|
export const createValidatorErrorHandler =
|
||||||
const validation = validationResult(req).formatWith(
|
(...args) =>
|
||||||
createValidatorErrorFormatter(...args)
|
(req, res, next) => {
|
||||||
);
|
const validation = validationResult(req).formatWith(
|
||||||
|
createValidatorErrorFormatter(...args)
|
||||||
|
);
|
||||||
|
|
||||||
if (!validation.isEmpty()) {
|
if (!validation.isEmpty()) {
|
||||||
const errors = validation.array();
|
const errors = validation.array();
|
||||||
return next(errors.pop());
|
return next(errors.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
};
|
};
|
||||||
|
@ -25,10 +25,14 @@ const propTypes = {
|
|||||||
showLoading: PropTypes.bool
|
showLoading: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
const createRequestedUserSelector = () => (state, { maybeUser = '' }) =>
|
const createRequestedUserSelector =
|
||||||
userByNameSelector(maybeUser.toLowerCase())(state);
|
() =>
|
||||||
const createIsSessionUserSelector = () => (state, { maybeUser = '' }) =>
|
(state, { maybeUser = '' }) =>
|
||||||
maybeUser.toLowerCase() === usernameSelector(state);
|
userByNameSelector(maybeUser.toLowerCase())(state);
|
||||||
|
const createIsSessionUserSelector =
|
||||||
|
() =>
|
||||||
|
(state, { maybeUser = '' }) =>
|
||||||
|
maybeUser.toLowerCase() === usernameSelector(state);
|
||||||
|
|
||||||
const makeMapStateToProps = () => (state, props) => {
|
const makeMapStateToProps = () => (state, props) => {
|
||||||
const requestedUserSelector = createRequestedUserSelector();
|
const requestedUserSelector = createRequestedUserSelector();
|
||||||
|
@ -14,15 +14,17 @@ function rendererCreateWithRedux(ui) {
|
|||||||
|
|
||||||
describe('<Intro />', () => {
|
describe('<Intro />', () => {
|
||||||
it('has no blockquotes when loggedOut', () => {
|
it('has no blockquotes when loggedOut', () => {
|
||||||
const container = rendererCreateWithRedux(<Intro {...loggedOutProps} />)
|
const container = rendererCreateWithRedux(
|
||||||
.root;
|
<Intro {...loggedOutProps} />
|
||||||
|
).root;
|
||||||
expect(container.findAllByType('blockquote').length === 0).toBeTruthy();
|
expect(container.findAllByType('blockquote').length === 0).toBeTruthy();
|
||||||
expect(container.findAllByType('h1').length === 1).toBeTruthy();
|
expect(container.findAllByType('h1').length === 1).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has a blockquote when loggedIn', () => {
|
it('has a blockquote when loggedIn', () => {
|
||||||
const container = rendererCreateWithRedux(<Intro {...loggedInProps} />)
|
const container = rendererCreateWithRedux(
|
||||||
.root;
|
<Intro {...loggedInProps} />
|
||||||
|
).root;
|
||||||
expect(container.findAllByType('blockquote').length === 1).toBeTruthy();
|
expect(container.findAllByType('blockquote').length === 1).toBeTruthy();
|
||||||
expect(container.findAllByType('h1').length === 1).toBeTruthy();
|
expect(container.findAllByType('h1').length === 1).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
@ -21,13 +21,8 @@ const propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ProjectModal = props => {
|
const ProjectModal = props => {
|
||||||
const {
|
const { isOpen, projectTitle, files, solution, handleSolutionModalHide } =
|
||||||
isOpen,
|
props;
|
||||||
projectTitle,
|
|
||||||
files,
|
|
||||||
solution,
|
|
||||||
handleSolutionModalHide
|
|
||||||
} = props;
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
|
|
||||||
const createRedirect = (to = '/') => () => {
|
const createRedirect =
|
||||||
if (typeof window !== 'undefined') {
|
(to = '/') =>
|
||||||
navigate(to);
|
() => {
|
||||||
}
|
if (typeof window !== 'undefined') {
|
||||||
return null;
|
navigate(to);
|
||||||
};
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
export default createRedirect;
|
export default createRedirect;
|
||||||
|
@ -2,8 +2,10 @@ import React from 'react';
|
|||||||
import { Trans } from 'react-i18next';
|
import { Trans } from 'react-i18next';
|
||||||
|
|
||||||
// Matches editor links for: Replit, Glitch, CodeSandbox, GitHub
|
// Matches editor links for: Replit, Glitch, CodeSandbox, GitHub
|
||||||
const editorRegex = /repl\.?it(\.com)?\/(@|join\/)|glitch\.com\/edit\/#!|codesandbox\.io\/s\/|github\.com/;
|
const editorRegex =
|
||||||
const fCCRegex = /codepen\.io\/freecodecamp|freecodecamp\.rocks|github\.com\/freecodecamp/i;
|
/repl\.?it(\.com)?\/(@|join\/)|glitch\.com\/edit\/#!|codesandbox\.io\/s\/|github\.com/;
|
||||||
|
const fCCRegex =
|
||||||
|
/codepen\.io\/freecodecamp|freecodecamp\.rocks|github\.com\/freecodecamp/i;
|
||||||
const localhostRegex = /localhost:/;
|
const localhostRegex = /localhost:/;
|
||||||
const httpRegex = /http(?!s|([^s]+?localhost))/;
|
const httpRegex = /http(?!s|([^s]+?localhost))/;
|
||||||
|
|
||||||
@ -21,5 +23,7 @@ export const localhostValidator = value =>
|
|||||||
export const httpValidator = value =>
|
export const httpValidator = value =>
|
||||||
httpRegex.test(value) ? <Trans>validation.http-url</Trans> : null;
|
httpRegex.test(value) ? <Trans>validation.http-url</Trans> : null;
|
||||||
|
|
||||||
export const composeValidators = (...validators) => value =>
|
export const composeValidators =
|
||||||
validators.reduce((error, validator) => error ?? validator?.(value), null);
|
(...validators) =>
|
||||||
|
value =>
|
||||||
|
validators.reduce((error, validator) => error ?? validator?.(value), null);
|
||||||
|
@ -285,13 +285,8 @@ export class CertificationSettings extends Component {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
renderProjectsFor = (certName, isCert) => {
|
renderProjectsFor = (certName, isCert) => {
|
||||||
const {
|
const { username, isHonest, createFlashMessage, t, verifyCert } =
|
||||||
username,
|
this.props;
|
||||||
isHonest,
|
|
||||||
createFlashMessage,
|
|
||||||
t,
|
|
||||||
verifyCert
|
|
||||||
} = this.props;
|
|
||||||
const { certSlug } = first(projectMap[certName]);
|
const { certSlug } = first(projectMap[certName]);
|
||||||
const certLocation = `/certification/${username}/${certSlug}`;
|
const certLocation = `/certification/${username}/${certSlug}`;
|
||||||
const createClickHandler = certSlug => e => {
|
const createClickHandler = certSlug => e => {
|
||||||
@ -332,12 +327,8 @@ export class CertificationSettings extends Component {
|
|||||||
|
|
||||||
// legacy projects rendering
|
// legacy projects rendering
|
||||||
handleSubmitLegacy({ values: formChalObj }) {
|
handleSubmitLegacy({ values: formChalObj }) {
|
||||||
const {
|
const { isHonest, createFlashMessage, verifyCert, updateLegacyCert } =
|
||||||
isHonest,
|
this.props;
|
||||||
createFlashMessage,
|
|
||||||
verifyCert,
|
|
||||||
updateLegacyCert
|
|
||||||
} = this.props;
|
|
||||||
let legacyTitle;
|
let legacyTitle;
|
||||||
let certSlug;
|
let certSlug;
|
||||||
let certs = Object.keys(legacyProjectMap);
|
let certs = Object.keys(legacyProjectMap);
|
||||||
|
@ -141,17 +141,11 @@ class EmailSettings extends Component {
|
|||||||
emailForm: { newEmail, confirmNewEmail, currentEmail, isPristine }
|
emailForm: { newEmail, confirmNewEmail, currentEmail, isPristine }
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const {
|
const { isEmailVerified, updateQuincyEmail, sendQuincyEmail, t } =
|
||||||
isEmailVerified,
|
this.props;
|
||||||
updateQuincyEmail,
|
|
||||||
sendQuincyEmail,
|
|
||||||
t
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const {
|
const { state: newEmailValidation, message: newEmailValidationMessage } =
|
||||||
state: newEmailValidation,
|
this.getValidationForNewEmail();
|
||||||
message: newEmailValidationMessage
|
|
||||||
} = this.getValidationForNewEmail();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
state: confirmEmailValidation,
|
state: confirmEmailValidation,
|
||||||
|
@ -165,20 +165,14 @@ class InternetSettings extends Component {
|
|||||||
message: githubProfileValidationMessage
|
message: githubProfileValidationMessage
|
||||||
} = this.getValidationStateFor(githubProfile);
|
} = this.getValidationStateFor(githubProfile);
|
||||||
|
|
||||||
const {
|
const { state: linkedinValidation, message: linkedinValidationMessage } =
|
||||||
state: linkedinValidation,
|
this.getValidationStateFor(linkedin);
|
||||||
message: linkedinValidationMessage
|
|
||||||
} = this.getValidationStateFor(linkedin);
|
|
||||||
|
|
||||||
const {
|
const { state: twitterValidation, message: twitterValidationMessage } =
|
||||||
state: twitterValidation,
|
this.getValidationStateFor(twitter);
|
||||||
message: twitterValidationMessage
|
|
||||||
} = this.getValidationStateFor(twitter);
|
|
||||||
|
|
||||||
const {
|
const { state: websiteValidation, message: websiteValidationMessage } =
|
||||||
state: websiteValidation,
|
this.getValidationStateFor(website);
|
||||||
message: websiteValidationMessage
|
|
||||||
} = this.getValidationStateFor(website);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -123,9 +123,8 @@ class PortfolioSettings extends Component {
|
|||||||
const { state: titleState } = this.getTitleValidation(title);
|
const { state: titleState } = this.getTitleValidation(title);
|
||||||
const { state: urlState } = this.getUrlValidation(url);
|
const { state: urlState } = this.getUrlValidation(url);
|
||||||
const { state: imageState } = this.getUrlValidation(image, true);
|
const { state: imageState } = this.getUrlValidation(image, true);
|
||||||
const { state: descriptionState } = this.getDescriptionValidation(
|
const { state: descriptionState } =
|
||||||
description
|
this.getDescriptionValidation(description);
|
||||||
);
|
|
||||||
return [titleState, imageState, urlState, descriptionState]
|
return [titleState, imageState, urlState, descriptionState]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.every(state => state === 'success');
|
.every(state => state === 'success');
|
||||||
@ -192,19 +191,15 @@ class PortfolioSettings extends Component {
|
|||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
const { id, title, description, url, image } = portfolio;
|
const { id, title, description, url, image } = portfolio;
|
||||||
const pristine = this.isFormPristine(id);
|
const pristine = this.isFormPristine(id);
|
||||||
const {
|
const { state: titleState, message: titleMessage } =
|
||||||
state: titleState,
|
this.getTitleValidation(title);
|
||||||
message: titleMessage
|
|
||||||
} = this.getTitleValidation(title);
|
|
||||||
const { state: urlState, message: urlMessage } = this.getUrlValidation(url);
|
const { state: urlState, message: urlMessage } = this.getUrlValidation(url);
|
||||||
const { state: imageState, message: imageMessage } = this.getUrlValidation(
|
const { state: imageState, message: imageMessage } = this.getUrlValidation(
|
||||||
image,
|
image,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
const {
|
const { state: descriptionState, message: descriptionMessage } =
|
||||||
state: descriptionState,
|
this.getDescriptionValidation(description);
|
||||||
message: descriptionMessage
|
|
||||||
} = this.getDescriptionValidation(description);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={id}>
|
<div key={id}>
|
||||||
|
@ -206,13 +206,8 @@ class ShowClassic extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderInstructionsPanel({ showToolPanel }) {
|
renderInstructionsPanel({ showToolPanel }) {
|
||||||
const {
|
const { block, description, instructions, superBlock, translationPending } =
|
||||||
block,
|
this.getChallenge();
|
||||||
description,
|
|
||||||
instructions,
|
|
||||||
superBlock,
|
|
||||||
translationPending
|
|
||||||
} = this.getChallenge();
|
|
||||||
|
|
||||||
const { forumTopicId, title } = this.getChallenge();
|
const { forumTopicId, title } = this.getChallenge();
|
||||||
return (
|
return (
|
||||||
|
@ -32,9 +32,8 @@ function createQuestionEpic(action$, state$, { window }) {
|
|||||||
tap(() => {
|
tap(() => {
|
||||||
const state = state$.value;
|
const state = state$.value;
|
||||||
const files = challengeFilesSelector(state);
|
const files = challengeFilesSelector(state);
|
||||||
const { title: challengeTitle, helpCategory } = challengeMetaSelector(
|
const { title: challengeTitle, helpCategory } =
|
||||||
state
|
challengeMetaSelector(state);
|
||||||
);
|
|
||||||
const {
|
const {
|
||||||
navigator: { userAgent },
|
navigator: { userAgent },
|
||||||
location: { href }
|
location: { href }
|
||||||
|
@ -74,9 +74,9 @@ export function* executeChallengeSaga({
|
|||||||
yield put(initLogs());
|
yield put(initLogs());
|
||||||
yield put(initConsole(i18next.t('learn.running-tests')));
|
yield put(initConsole(i18next.t('learn.running-tests')));
|
||||||
// reset tests to initial state
|
// reset tests to initial state
|
||||||
const tests = (yield select(
|
const tests = (yield select(challengeTestsSelector)).map(
|
||||||
challengeTestsSelector
|
({ text, testString }) => ({ text, testString })
|
||||||
)).map(({ text, testString }) => ({ text, testString }));
|
);
|
||||||
yield put(updateTests(tests));
|
yield put(updateTests(tests));
|
||||||
|
|
||||||
yield fork(takeEveryLog, consoleProxy);
|
yield fork(takeEveryLog, consoleProxy);
|
||||||
|
@ -67,22 +67,24 @@ const createFrame = (document, id) => ctx => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const hiddenFrameClassName = 'hide-test-frame';
|
const hiddenFrameClassName = 'hide-test-frame';
|
||||||
const mountFrame = document => ({ element, ...rest }) => {
|
const mountFrame =
|
||||||
const oldFrame = document.getElementById(element.id);
|
document =>
|
||||||
if (oldFrame) {
|
({ element, ...rest }) => {
|
||||||
element.className = oldFrame.className || hiddenFrameClassName;
|
const oldFrame = document.getElementById(element.id);
|
||||||
oldFrame.parentNode.replaceChild(element, oldFrame);
|
if (oldFrame) {
|
||||||
} else {
|
element.className = oldFrame.className || hiddenFrameClassName;
|
||||||
element.className = hiddenFrameClassName;
|
oldFrame.parentNode.replaceChild(element, oldFrame);
|
||||||
document.body.appendChild(element);
|
} else {
|
||||||
}
|
element.className = hiddenFrameClassName;
|
||||||
return {
|
document.body.appendChild(element);
|
||||||
...rest,
|
}
|
||||||
element,
|
return {
|
||||||
document: element.contentDocument,
|
...rest,
|
||||||
window: element.contentWindow
|
element,
|
||||||
|
document: element.contentDocument,
|
||||||
|
window: element.contentWindow
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const buildProxyConsole = proxyLogger => ctx => {
|
const buildProxyConsole = proxyLogger => ctx => {
|
||||||
const oldLog = ctx.window.console.log.bind(ctx.window.console);
|
const oldLog = ctx.window.console.log.bind(ctx.window.console);
|
||||||
|
@ -20,9 +20,11 @@ const CertificationCard = ({ certSlug, superBlock, i18nCertText }) => {
|
|||||||
setIsExpanded(!isExpanded);
|
setIsExpanded(!isExpanded);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { expand: expandText, collapse: collapseText, steps: stepsText } = t(
|
const {
|
||||||
'intro:misc-text'
|
expand: expandText,
|
||||||
);
|
collapse: collapseText,
|
||||||
|
steps: stepsText
|
||||||
|
} = t('intro:misc-text');
|
||||||
return (
|
return (
|
||||||
<ScrollableAnchor id='claim-cert-block'>
|
<ScrollableAnchor id='claim-cert-block'>
|
||||||
<div className={`block ${isExpanded ? 'open' : ''}`}>
|
<div className={`block ${isExpanded ? 'open' : ''}`}>
|
||||||
|
@ -14,10 +14,8 @@ function SuperBlockIntro(props) {
|
|||||||
const { superBlock } = props;
|
const { superBlock } = props;
|
||||||
|
|
||||||
const superBlockIntroObj = t(`intro:${superBlock}`);
|
const superBlockIntroObj = t(`intro:${superBlock}`);
|
||||||
const {
|
const { title: i18nSuperBlock, intro: superBlockIntroText } =
|
||||||
title: i18nSuperBlock,
|
superBlockIntroObj;
|
||||||
intro: superBlockIntroText
|
|
||||||
} = superBlockIntroObj;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -8,10 +8,8 @@ import htmlTestValues from './__fixtures/curriculum-helpers-html';
|
|||||||
import whiteSpaceTestValues from './__fixtures/curriculum-helpers-remove-white-space';
|
import whiteSpaceTestValues from './__fixtures/curriculum-helpers-remove-white-space';
|
||||||
/* eslint-enable max-len */
|
/* eslint-enable max-len */
|
||||||
|
|
||||||
const {
|
const { stringWithWhiteSpaceChars, stringWithWhiteSpaceCharsRemoved } =
|
||||||
stringWithWhiteSpaceChars,
|
whiteSpaceTestValues;
|
||||||
stringWithWhiteSpaceCharsRemoved
|
|
||||||
} = whiteSpaceTestValues;
|
|
||||||
|
|
||||||
const { cssFullExample, cssCodeWithCommentsRemoved } = cssTestValues;
|
const { cssFullExample, cssCodeWithCommentsRemoved } = cssTestValues;
|
||||||
|
|
||||||
|
@ -49,36 +49,38 @@ const getPrevChallengePath = (node, index, nodeArray) => {
|
|||||||
|
|
||||||
const getTemplateComponent = challengeType => views[viewTypes[challengeType]];
|
const getTemplateComponent = challengeType => views[viewTypes[challengeType]];
|
||||||
|
|
||||||
exports.createChallengePages = createPage => ({ node }, index, thisArray) => {
|
exports.createChallengePages =
|
||||||
const {
|
createPage =>
|
||||||
superBlock,
|
({ node }, index, thisArray) => {
|
||||||
block,
|
const {
|
||||||
fields: { slug },
|
superBlock,
|
||||||
required = [],
|
block,
|
||||||
template,
|
fields: { slug },
|
||||||
challengeType,
|
required = [],
|
||||||
id
|
template,
|
||||||
} = node;
|
challengeType,
|
||||||
// TODO: challengeType === 7 and isPrivate are the same, right? If so, we
|
id
|
||||||
// should remove one of them.
|
} = node;
|
||||||
|
// TODO: challengeType === 7 and isPrivate are the same, right? If so, we
|
||||||
|
// should remove one of them.
|
||||||
|
|
||||||
return createPage({
|
return createPage({
|
||||||
path: slug,
|
path: slug,
|
||||||
component: getTemplateComponent(challengeType),
|
component: getTemplateComponent(challengeType),
|
||||||
context: {
|
context: {
|
||||||
challengeMeta: {
|
challengeMeta: {
|
||||||
superBlock,
|
superBlock,
|
||||||
block,
|
block,
|
||||||
template,
|
template,
|
||||||
required,
|
required,
|
||||||
nextChallengePath: getNextChallengePath(node, index, thisArray),
|
nextChallengePath: getNextChallengePath(node, index, thisArray),
|
||||||
prevChallengePath: getPrevChallengePath(node, index, thisArray),
|
prevChallengePath: getPrevChallengePath(node, index, thisArray),
|
||||||
id
|
id
|
||||||
},
|
},
|
||||||
slug
|
slug
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.createBlockIntroPages = createPage => edge => {
|
exports.createBlockIntroPages = createPage => edge => {
|
||||||
const {
|
const {
|
||||||
|
@ -15,9 +15,8 @@ const { isAuditedCert } = require('../utils/is-audited');
|
|||||||
const { dasherize } = require('../utils/slugs');
|
const { dasherize } = require('../utils/slugs');
|
||||||
const { createPoly } = require('../utils/polyvinyl');
|
const { createPoly } = require('../utils/polyvinyl');
|
||||||
const { helpCategoryMap } = require('../client/utils/challengeTypes');
|
const { helpCategoryMap } = require('../client/utils/challengeTypes');
|
||||||
const {
|
const { curriculum: curriculumLangs } =
|
||||||
curriculum: curriculumLangs
|
require('../config/i18n/all-langs').availableLangs;
|
||||||
} = require('../config/i18n/all-langs').availableLangs;
|
|
||||||
|
|
||||||
const access = util.promisify(fs.access);
|
const access = util.promisify(fs.access);
|
||||||
|
|
||||||
|
@ -68,9 +68,10 @@ const TRANSLATABLE_COMMENTS = getTranslatableComments(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// the config files are created during the build, but not before linting
|
// the config files are created during the build, but not before linting
|
||||||
// eslint-disable-next-line import/no-unresolved
|
/* eslint-disable import/no-unresolved */
|
||||||
const testEvaluator = require('../../config/client/test-evaluator.json')
|
const testEvaluator =
|
||||||
.filename;
|
require('../../config/client/test-evaluator.json').filename;
|
||||||
|
/* eslint-enable import/no-unresolved */
|
||||||
const { inspect } = require('util');
|
const { inspect } = require('util');
|
||||||
|
|
||||||
const commentExtractors = {
|
const commentExtractors = {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
|
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
|
||||||
|
|
||||||
const {
|
const { curriculum: curriculumLangs } =
|
||||||
curriculum: curriculumLangs
|
require('../config/i18n/all-langs').availableLangs;
|
||||||
} = require('../config/i18n/all-langs').availableLangs;
|
|
||||||
|
|
||||||
exports.testedLang = function testedLang() {
|
exports.testedLang = function testedLang() {
|
||||||
if (process.env.CURRICULUM_LOCALE) {
|
if (process.env.CURRICULUM_LOCALE) {
|
||||||
|
@ -20,8 +20,7 @@ describe('The Document Metadata', () => {
|
|||||||
const scripts = {
|
const scripts = {
|
||||||
mathjax: {
|
mathjax: {
|
||||||
selector: 'body script[id="mathjax"]',
|
selector: 'body script[id="mathjax"]',
|
||||||
src:
|
src: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS_HTML'
|
||||||
'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS_HTML'
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
it('landing page has correct <meta> for description', () => {
|
it('landing page has correct <meta> for description', () => {
|
||||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -16457,9 +16457,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"version": "2.2.1",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz",
|
||||||
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
|
"integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"prettier-linter-helpers": {
|
"prettier-linter-helpers": {
|
||||||
|
@ -117,7 +117,7 @@
|
|||||||
"markdownlint": "0.21.0",
|
"markdownlint": "0.21.0",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "4.1.5",
|
||||||
"ora": "5.4.0",
|
"ora": "5.4.0",
|
||||||
"prettier": "2.2.1",
|
"prettier": "2.3.0",
|
||||||
"prismjs": "1.23.0",
|
"prismjs": "1.23.0",
|
||||||
"shx": "0.3.3",
|
"shx": "0.3.3",
|
||||||
"sinon": "10.0.0",
|
"sinon": "10.0.0",
|
||||||
|
@ -44,9 +44,8 @@ const hideNonTranslatedStrings = async projectId => {
|
|||||||
const crowdinStrings = await getStrings({ projectId });
|
const crowdinStrings = await getStrings({ projectId });
|
||||||
if (crowdinStrings && crowdinStrings.length) {
|
if (crowdinStrings && crowdinStrings.length) {
|
||||||
for (let string of crowdinStrings) {
|
for (let string of crowdinStrings) {
|
||||||
const { crowdinFilePath, challengeTitle } = challengeTitleLookup[
|
const { crowdinFilePath, challengeTitle } =
|
||||||
string.data.fileId
|
challengeTitleLookup[string.data.fileId];
|
||||||
];
|
|
||||||
await updateFileString({
|
await updateFileString({
|
||||||
projectId,
|
projectId,
|
||||||
string,
|
string,
|
||||||
|
Reference in New Issue
Block a user