diff --git a/common/app/entities/index.js b/common/app/entities/index.js
index bb8aeda1c1..d0367de9b5 100644
--- a/common/app/entities/index.js
+++ b/common/app/entities/index.js
@@ -196,13 +196,12 @@ export default composeReducers(
app.fetchChallenges.complete,
map.fetchMapUi.complete
)
- ]: (state, { payload }) => {
- const {entities: { block } } = payload;
- return {
- ...merge(state, payload.entities),
- fullBlocks: union(state.fullBlocks, [ Object.keys(block)[0] ])
- };
- },
+ ]: (state, { payload: { entities } }) => merge({}, state, entities),
+ [app.fetchChallenges.complete]:
+ (state, { payload: { entities: { block }}}) => ({
+ ...state,
+ fullBlocks: union(state.fullBlocks, [ Object.keys(block)[0] ])
+ }),
[
challenges.submitChallenge.complete
]: (state, { payload: { username, points, challengeInfo } }) => ({
diff --git a/common/app/helperComponents/OverlayLoader.jsx b/common/app/helperComponents/OverlayLoader.jsx
index 6ca095a494..880ed41ece 100644
--- a/common/app/helperComponents/OverlayLoader.jsx
+++ b/common/app/helperComponents/OverlayLoader.jsx
@@ -27,20 +27,20 @@ LoaderCircle.displayName = 'LoaderCircle';
const animationProps = [
{
- delay: '-1.5s',
- origin: '1% 1%'
+ delay: '0.24s',
+ origin: '0% 0%'
},
{
- delay: '-1s',
- origin: '1% 99%'
+ delay: '0.95s',
+ origin: '0% 100%'
},
{
- delay: '-0.5s',
- origin: '99% 1%'
+ delay: '0.67s',
+ origin: '100% 0%'
},
{
- delay: '0s',
- origin: '99% 99%'
+ delay: '1.33s',
+ origin: '100% 100%'
}
];
diff --git a/common/app/helperComponents/overlayLoader-styles.js b/common/app/helperComponents/overlayLoader-styles.js
index 11ce0f43cc..c710ed37ea 100644
--- a/common/app/helperComponents/overlayLoader-styles.js
+++ b/common/app/helperComponents/overlayLoader-styles.js
@@ -28,13 +28,18 @@ export default `
transform: scale(0.1);
opacity: 0;
}
+ 50% {
+ -webkit-transform: scale(0.8);
+ transform: scale(0.8);
+ opacity: 0.8;
+ }
70% {
opacity: 1;
}
100% {
- opacity: 0.0;
- -webkit-transform: scale(1);
- transform: scale(1);
+ opacity: 0;
+ -webkit-transform: scale(1.2);
+ transform: scale(1.2);
}
}
@@ -55,14 +60,15 @@ export default `
}
.innerCircle {
- -webkit-animation-duration: 2s;
- animation-duration: 2s;
- -webkit-animation-iteration-count: infinite;
- animation-iteration-count: infinite;
- -webkit-animation-name: overlay-loader;
- animation-name: overlay-loader;
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
+ -webkit-animation-duration: 2s;
+ animation-duration: 2s;
+ -webkit-animation-iteration-count: infinite;
+ animation-iteration-count: infinite;
+ -webkit-animation-name: overlay-loader;
+ animation-name: overlay-loader;
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out;
+ opacity: 0;
}
`;
diff --git a/common/app/routes/Challenges/Show.jsx b/common/app/routes/Challenges/Show.jsx
index f8a4ac62ab..7f4931d8a6 100644
--- a/common/app/routes/Challenges/Show.jsx
+++ b/common/app/routes/Challenges/Show.jsx
@@ -45,7 +45,7 @@ const mapStateToProps = createSelector(
paramsSelector,
fullBlocksSelector,
(
- { dashedName, isTranslated },
+ { dashedName, isTranslated, description },
{ viewType, title },
params,
blocks
@@ -54,6 +54,7 @@ const mapStateToProps = createSelector(
challenge: dashedName,
isTranslated,
params,
+ showLoading: !description || description.length === 0,
title,
viewType
})
@@ -71,6 +72,7 @@ const propTypes = {
dashedName: PropTypes.string,
lang: PropTypes.string.isRequired
}),
+ showLoading: PropTypes.bool,
title: PropTypes.string,
updateSuccessMessage: PropTypes.func.isRequired,
updateTitle: PropTypes.func.isRequired,
@@ -113,9 +115,9 @@ export class Show extends PureComponent {
}
render() {
- const { viewType } = this.props;
+ const { viewType, showLoading } = this.props;
const View = views[viewType] || Classic;
- return ;
+ return ;
}
}
diff --git a/common/app/routes/Challenges/Side-Panel.jsx b/common/app/routes/Challenges/Side-Panel.jsx
index b69e48ba09..79de055b07 100644
--- a/common/app/routes/Challenges/Side-Panel.jsx
+++ b/common/app/routes/Challenges/Side-Panel.jsx
@@ -30,13 +30,6 @@ import { descriptionRegex } from './utils';
import { challengeSelector } from '../../redux';
import { makeToast } from '../../Toasts/redux';
-const mapDispatchToProps = {
- makeToast,
- executeChallenge,
- updateHint,
- openHelpModal,
- unlockUntrustedCode
-};
const mapStateToProps = createSelector(
challengeSelector,
challengeMetaSelector,
@@ -62,6 +55,15 @@ const mapStateToProps = createSelector(
isCodeLocked
})
);
+
+const mapDispatchToProps = {
+ makeToast,
+ executeChallenge,
+ updateHint,
+ openHelpModal,
+ unlockUntrustedCode
+};
+
const propTypes = {
description: PropTypes.arrayOf(PropTypes.string),
executeChallenge: PropTypes.func,
@@ -95,7 +97,8 @@ export class SidePanel extends PureComponent {
this.descriptionTop = node;
}
- renderDescription(description = [ 'Happy Coding!' ]) {
+ renderDescription() {
+ const { description = [ 'Happy Coding!' ] } = this.props;
return description.map((line, index) => {
if (descriptionRegex.test(line)) {
return (
@@ -118,7 +121,6 @@ export class SidePanel extends PureComponent {
render() {
const {
title,
- description,
tests = [],
output,
hint,
@@ -142,7 +144,7 @@ export class SidePanel extends PureComponent {
{ title }
- { this.renderDescription(description) }
+ { this.renderDescription() }
const getFirstFileKey = _.flow(_.values, _.first, _.property('key'));
const propTypes = {
- nameToFileKey: PropTypes.object
+ nameToFileKey: PropTypes.object,
+ showLoading: PropTypes.bool
};
const mapStateToProps = createSelector(
@@ -83,9 +85,12 @@ const nameToComponent = {
Preview: Preview
};
-export function ShowModern({ nameToFileKey }) {
+export function ShowModern({ nameToFileKey, showLoading }) {
return (
+ {
+ showLoading ? : null
+ }
{
const Comp = nameToComponent[name];
diff --git a/common/app/routes/Challenges/views/backend/Show.jsx b/common/app/routes/Challenges/views/backend/Show.jsx
index e69702c750..c94ddca3cf 100644
--- a/common/app/routes/Challenges/views/backend/Show.jsx
+++ b/common/app/routes/Challenges/views/backend/Show.jsx
@@ -1,13 +1,17 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { addNS } from 'berkeleys-redux-utils';
+import { OverlayLoader } from '../../../../helperComponents';
import ChildContainer from '../../Child-Container.jsx';
import BackEnd from './Back-End.jsx';
import { types } from '../../redux';
import Panes from '../../../../Panes';
import _Map from '../../../../Map';
-const propTypes = {};
+const propTypes = {
+ showLoading: PropTypes.bool
+};
export const mapStateToPanes = addNS(
'backend',
@@ -27,9 +31,12 @@ const renderPane = name => {
return Comp ? : Pane { name } not found;
};
-export default function ShowBackEnd() {
+export default function ShowBackEnd({ showLoading }) {
return (
+ {
+ showLoading ? : null
+ }
);
diff --git a/common/app/routes/Challenges/views/classic/Show.jsx b/common/app/routes/Challenges/views/classic/Show.jsx
index b82d361c6d..5d841bc0c4 100644
--- a/common/app/routes/Challenges/views/classic/Show.jsx
+++ b/common/app/routes/Challenges/views/classic/Show.jsx
@@ -1,15 +1,19 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { addNS } from 'berkeleys-redux-utils';
import Editor from './Editor.jsx';
import ChildContainer from '../../Child-Container.jsx';
+import { OverlayLoader } from '../../../../helperComponents';
import { types, showPreviewSelector } from '../../redux';
import Preview from '../../Preview.jsx';
import SidePanel from '../../Side-Panel.jsx';
import Panes from '../../../../Panes';
import _Map from '../../../../Map';
-const propTypes = {};
+const propTypes = {
+ showLoading: PropTypes.bool
+};
export const mapStateToPanes = addNS(
'classic',
@@ -39,9 +43,12 @@ const renderPane = name => {
return Comp ? : Pane for { name } not found;
};
-export default function ShowClassic() {
+export default function ShowClassic({ showLoading }) {
return (
+ {
+ showLoading ? : null
+ }
);
diff --git a/common/app/routes/Challenges/views/project/Show.jsx b/common/app/routes/Challenges/views/project/Show.jsx
index 9f7de7e7e0..8e021fd481 100644
--- a/common/app/routes/Challenges/views/project/Show.jsx
+++ b/common/app/routes/Challenges/views/project/Show.jsx
@@ -1,14 +1,18 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { addNS } from 'berkeleys-redux-utils';
import ns from './ns.json';
import Main from './Project.jsx';
+import { OverlayLoader } from '../../../../helperComponents';
import ChildContainer from '../../Child-Container.jsx';
import { types } from '../../redux';
import Panes from '../../../../Panes';
import _Map from '../../../../Map';
-const propTypes = {};
+const propTypes = {
+ showLoading: PropTypes.bool
+};
export const mapStateToPanes = addNS(
ns,
() => ({
@@ -27,9 +31,12 @@ const renderPane = name => {
return Comp ? : Pane { name } not found;
};
-export default function ShowProject() {
+export default function ShowProject({ showLoading }) {
return (
+ {
+ showLoading ? : null
+ }
);
diff --git a/common/app/routes/Challenges/views/quiz/Show.jsx b/common/app/routes/Challenges/views/quiz/Show.jsx
index 7937804521..302ac4ccfc 100644
--- a/common/app/routes/Challenges/views/quiz/Show.jsx
+++ b/common/app/routes/Challenges/views/quiz/Show.jsx
@@ -1,14 +1,18 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { addNS } from 'berkeleys-redux-utils';
import ns from './ns.json';
import Main from './Quiz.jsx';
+import { OverlayLoader } from '../../../../helperComponents';
import ChildContainer from '../../Child-Container.jsx';
import { types } from '../../redux';
import Panes from '../../../../Panes';
import _Map from '../../../../Map';
-const propTypes = {};
+const propTypes = {
+ showLoading: PropTypes.bool
+};
export const mapStateToPanes = addNS(
ns,
() => ({
@@ -27,9 +31,12 @@ const renderPane = name => {
return Comp ? : Pane { name } not found;
};
-export default function ShowQuiz() {
+export default function ShowQuiz({ showLoading }) {
return (
+ {
+ showLoading ? : null
+ }
);
diff --git a/common/app/routes/Challenges/views/step/Show.jsx b/common/app/routes/Challenges/views/step/Show.jsx
index 31c4370454..4a7d25e107 100644
--- a/common/app/routes/Challenges/views/step/Show.jsx
+++ b/common/app/routes/Challenges/views/step/Show.jsx
@@ -1,14 +1,18 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { addNS } from 'berkeleys-redux-utils';
import ns from './ns.json';
import Step from './Step.jsx';
+import { OverlayLoader } from '../../../../helperComponents';
import ChildContainer from '../../Child-Container.jsx';
import { types } from '../../redux';
import Panes from '../../../../Panes';
import _Map from '../../../../Map';
-const propTypes = {};
+const propTypes = {
+ showLoading: PropTypes.bool
+};
export const mapStateToPanes = addNS(
ns,
() => ({
@@ -27,9 +31,12 @@ const renderPane = name => {
return Comp ? : Pane { name } not found;
};
-export default function ShowStep() {
+export default function ShowStep({ showLoading }) {
return (
+ {
+ showLoading ? : null
+ }
);
diff --git a/common/app/routes/Challenges/views/step/Step.jsx b/common/app/routes/Challenges/views/step/Step.jsx
index 921af0b797..b1da72ca7d 100644
--- a/common/app/routes/Challenges/views/step/Step.jsx
+++ b/common/app/routes/Challenges/views/step/Step.jsx
@@ -31,7 +31,7 @@ const mapStateToProps = createSelector(
actionCompletedSelector,
lightBoxSelector,
(
- { description = [] },
+ { description = [['', '', 'Happy Coding!', '']] },
currentIndex,
previousIndex,
isActionCompleted,
diff --git a/server/services/mapUi.js b/server/services/mapUi.js
index 9360deac3e..adb313b006 100644
--- a/server/services/mapUi.js
+++ b/server/services/mapUi.js
@@ -58,7 +58,8 @@ export default function mapUiService(app) {
block,
isLocked,
isComingSoon,
- isBeta
+ isBeta,
+ challengeType
} = challenge;
map[dashedName] = {
dashedName,
@@ -68,7 +69,8 @@ export default function mapUiService(app) {
block,
isLocked,
isComingSoon,
- isBeta
+ isBeta,
+ challengeType
};
return map;
}, {});