diff --git a/client/less/toastr.less b/client/less/toastr.less
index de17335ed3..018c3aff77 100644
--- a/client/less/toastr.less
+++ b/client/less/toastr.less
@@ -8,3 +8,9 @@
.notification-bar-message {
padding-right: 2rem;
}
+
+.notification-bar-action > a {
+ &:hover {
+ color: #007c00;
+ }
+}
diff --git a/common/app/routes/challenges/components/Show.jsx b/common/app/routes/challenges/components/Show.jsx
index 06f73a9655..c163ed5199 100644
--- a/common/app/routes/challenges/components/Show.jsx
+++ b/common/app/routes/challenges/components/Show.jsx
@@ -18,6 +18,7 @@ import {
} from '../redux/actions';
import { challengeSelector } from '../redux/selectors';
import { updateTitle } from '../../../redux/actions';
+import { makeToast } from '../../../toasts/redux/actions';
const views = {
step: Step,
@@ -30,6 +31,7 @@ const views = {
const bindableActions = {
fetchChallenge,
fetchChallenges,
+ makeToast,
replaceChallenge,
resetUi,
updateTitle
@@ -39,7 +41,17 @@ const mapStateToProps = createSelector(
challengeSelector,
state => state.challengesApp.challenge,
state => state.challengesApp.superBlocks,
- ({ challenge: { title } = {}, viewType }, challenge, superBlocks = []) => ({
+ state => state.app.lang,
+ (
+ {
+ challenge: { title, isTranslated } = {}, viewType
+ },
+ challenge,
+ superBlocks = [],
+ lang
+ ) => ({
+ lang,
+ isTranslated,
title,
challenge,
viewType,
@@ -57,6 +69,10 @@ const fetchOptions = {
}
};
+const link = 'http://forum.freecodecamp.com/t/' +
+ 'guidelines-for-translating-free-code-camp' +
+ '-to-any-language/19111';
+
export class Challenges extends PureComponent {
static displayName = 'Challenges';
@@ -69,11 +85,22 @@ export class Challenges extends PureComponent {
params: PropTypes.object.isRequired,
areChallengesLoaded: PropTypes.bool,
resetUi: PropTypes.func.isRequired,
- updateTitle: PropTypes.func.isRequired
+ updateTitle: PropTypes.func.isRequired,
+ makeToast: PropTypes.func.isRequired,
+ lang: PropTypes.string.isRequired,
+ isTranslated: PropTypes.bool
};
componentWillMount() {
- this.props.updateTitle(this.props.title);
+ const { title, updateTitle, lang, isTranslated, makeToast } = this.props;
+ updateTitle(title);
+ if (lang !== 'en' && !isTranslated) {
+ makeToast({
+ message: 'We haven\'t translated this challenge yet.',
+ action: Help Us,
+ timeout: 15000
+ });
+ }
}
componentDidMount() {
@@ -88,11 +115,19 @@ export class Challenges extends PureComponent {
componentWillReceiveProps(nextProps) {
const { block, dashedName } = nextProps.params;
- const { resetUi, updateTitle, replaceChallenge } = this.props;
+ const { lang, isTranslated } = nextProps;
+ const { resetUi, updateTitle, replaceChallenge, makeToast } = this.props;
if (this.props.params.dashedName !== dashedName) {
updateTitle(nextProps.title);
resetUi();
replaceChallenge({ dashedName, block });
+ if (lang !== 'en' && !isTranslated) {
+ makeToast({
+ message: 'We haven\'t translated this challenge yet.',
+ action: Help Us,
+ timeout: 15000
+ });
+ }
}
}
diff --git a/common/app/toasts/Toasts.jsx b/common/app/toasts/Toasts.jsx
index 3955bc2b1b..3f82df82d4 100644
--- a/common/app/toasts/Toasts.jsx
+++ b/common/app/toasts/Toasts.jsx
@@ -42,7 +42,9 @@ const addDispatchableActionsToToast = createSelector(
finalBarStyle = rightBarStyle;
}
const onClick = !registeredActions[actionCreator] ?
- null :
+ () => {
+ dispatch(removeToast(toast));
+ } :
() => {
dispatch(registeredActions[actionCreator]());
dispatch(removeToast(toast));
diff --git a/server/utils/map.js b/server/utils/map.js
index 8dfe32f824..e530ff1890 100644
--- a/server/utils/map.js
+++ b/server/utils/map.js
@@ -111,13 +111,18 @@ export function mapChallengeToLang(
lang = 'en';
}
const translation = translations[lang] || {};
+ const isTranslated = Object.keys(translation).length > 0;
if (lang !== 'en') {
challenge = {
...challenge,
- ...translation
+ ...translation,
+ isTranslated
};
}
- return challenge;
+ return {
+ ...challenge,
+ isTranslated
+ };
}
export function getMapForLang(lang) {
@@ -133,4 +138,3 @@ export function getMapForLang(lang) {
return { result, entities };
};
}
-