Skip to content

Commit

Permalink
Merge pull request #13961 from code-dot-org/staging
Browse files Browse the repository at this point in the history
DTT (Staging > Test) [robo-dtt]
  • Loading branch information
ashercodeorg committed Mar 23, 2017
2 parents d2dcd95 + 8002bed commit d0bac56
Show file tree
Hide file tree
Showing 47 changed files with 734 additions and 119 deletions.
8 changes: 4 additions & 4 deletions apps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@
"@code-dot-org/blockly": "1.6.9",
"@code-dot-org/bramble": "0.1.11",
"@code-dot-org/js-numbers": "0.1.0-cdo.0",
"@code-dot-org/p5.play": "1.1.5-cdo",
"@code-dot-org/p5.play": "1.1.6-cdo",
"@code-dot-org/piskel": "0.10.0-cdo.0",
"@kadira/react-storybook-addon-info": "^3.3.0",
"@kadira/storybook": "^2.33.0",
"aws-sdk": "2.28.0",
"Base64": "0.3.0",
"aws-sdk": "2.28.0",
"babel-core": "6.9.0",
"babel-eslint": "^7.1.1",
"babel-istanbul-loader": "^0.1.0",
Expand Down Expand Up @@ -177,8 +177,8 @@
"sass-loader": "^4.0.2",
"script-loader": "^0.7.0",
"seedrandom": "2.4.2",
"sinon": "^2.0.0-pre",
"sinon-chai": "^2.8.0",
"sinon": "^2.1.0",
"sinon-chai": "^2.9.0",
"sprintf-js": "^1.0.3",
"stackblur": "^1.0.0",
"style-loader": "^0.13.1",
Expand Down
15 changes: 9 additions & 6 deletions apps/src/code-studio/components/progress/ProgressDot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ export const ProgressDot = Radium(React.createClass({
return '';
},

tooltipId() {
return (this.props.level.title || "").toString();
},

tooltipContent() {
const { level } = this.props;
if (level.name === undefined) {
Expand All @@ -235,11 +239,11 @@ export const ProgressDot = Radium(React.createClass({
},

renderTooltip() {
const { level, courseOverviewPage } = this.props;
const { courseOverviewPage } = this.props;
if (!courseOverviewPage) {
return (
<ReactTooltip
id={level.title}
id={this.tooltipId()}
role="tooltip"
wrapper="span"
>
Expand All @@ -249,7 +253,6 @@ export const ProgressDot = Radium(React.createClass({
}
},


render() {

const { level, status, courseOverviewPage, currentLevelId } = this.props;
Expand Down Expand Up @@ -279,7 +282,7 @@ export const ProgressDot = Radium(React.createClass({
]}
>
{(iconClassFromIconType[level.icon] && !isPeerReview) ?
<span data-tip data-for={level.title} aria-describedby={level.title} style={{borderColor: "#ff0000", borderWidth: 2}}>
<span data-tip data-for={this.tooltipId()} aria-describedby={this.tooltipId()} style={{borderColor: "#ff0000", borderWidth: 2}}>
<i
className={this.iconClassName()}
style={[
Expand Down Expand Up @@ -309,11 +312,11 @@ export const ProgressDot = Radium(React.createClass({
]}
>

<div data-tip data-for={level.title} aria-describedby={level.title}>
<div data-tip data-for={this.tooltipId()} aria-describedby={this.tooltipId()}>
<BubbleInterior
showingIcon={!!this.iconClassName()}
showingLevelName={showLevelName}
title={level.title || undefined}
title={this.tooltipId() || undefined}
/>
{this.renderTooltip()}
</div>
Expand Down
61 changes: 54 additions & 7 deletions apps/src/code-studio/progressRedux.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const SET_IS_HOC_SCRIPT = 'progress/SET_IS_HOC_SCRIPT';
const SET_IS_SUMMARY_VIEW = 'progress/SET_IS_SUMMARY_VIEW';

export const SignInState = makeEnum('Unknown', 'SignedIn', 'SignedOut');
const PEER_REVIEW_ID = -1;

const initialState = {
// These first fields never change after initialization
Expand Down Expand Up @@ -56,7 +57,7 @@ export default function reducer(state = initialState, action) {
currentLevelId: action.currentLevelId,
professionalLearningCourse: action.professionalLearningCourse,
saveAnswersBeforeNavigation: action.saveAnswersBeforeNavigation,
stages: processedStages(stages),
stages: processedStages(stages, action.professionalLearningCourse),
peerReviewStage: action.peerReviewStage,
scriptName: action.scriptName,
currentStageId
Expand Down Expand Up @@ -174,14 +175,14 @@ function bestResultLevelId(levelIds, progressData) {
/**
* Does some processing of our passed in stages, namely
* - Removes 'hidden' field
* - Adds 'stageNumber' field for non-lockable stages
* - Adds 'stageNumber' field for non-lockable, non-PLC stages
*/
export function processedStages(stages) {
export function processedStages(stages, isPlc) {
let numberOfNonLockableStages = 0;

return stages.map(stage => {
let stageNumber;
if (!stage.lockable) {
if (!isPlc && !stage.lockable) {
numberOfNonLockableStages++;
stageNumber = numberOfNonLockableStages;
}
Expand Down Expand Up @@ -238,10 +239,42 @@ export const hasGroups = state => Object.keys(categorizedLessons(state)).length
/**
* Extract the relevant portions of a particular lesson/stage from the store.
* Note, that this does not include levels
* @param {object} state - The progress state in our redux store
* @param {number} stageIndex - The index into our stages we care about
* @returns {Lesson}
*/
const lessonFromStageAtIndex = (state, stageIndex) => ({
...lessonFromStage(state.stages[stageIndex]),
isFocusArea: state.focusAreaPositions.includes(state.stages[stageIndex].position)
});
const lessonFromStage = stage => _.pick(stage, ['name', 'id', 'lockable', 'stageNumber', 'lesson_plan_html_url']);
export const lessons = state => state.stages.map(lessonFromStage);
export const lessons = state => state.stages.map((_, index) => lessonFromStageAtIndex(state, index));

/**
* Extract lesson from our peerReviewStage if we have one. We want this to end up
* having the same fields as our non-peer review stages.
*/
const peerReviewLesson = state => ({
...lessonFromStage(state.peerReviewStage),
// add some fields that are missing for this stage but required for lessonType
id: PEER_REVIEW_ID,
lockable: false,
isFocusArea: false
});

/**
* Extract levels from our peerReviewStage, making sure the levels have the same
* set of fields as our non-peer review levels.
*/
const peerReviewLevels = state => state.peerReviewStage.levels.map((level, index) => ({
// These aren't true levels (i.e. we won't have an entry in levelProgress),
// so always use a specific id that won't collide with real levels
id: PEER_REVIEW_ID,
status: (level.locked ? LevelStatus.locked : level.status),
url: level.url,
name: level.name,
icon: (level.locked ? level.icon : undefined),
}));

/**
* The level object passed down to use via the server (and stored in stage.stages.levels)
Expand Down Expand Up @@ -309,7 +342,7 @@ export const categorizedLessons = state => {

state.stages.forEach((stage, index) => {
const category = stage.flex_category;
const lesson = lessonFromStage(stage);
const lesson = lessonFromStageAtIndex(state, index);
const stageLevels = allLevels[index];

byCategory[category] = byCategory[category] || {
Expand All @@ -322,6 +355,17 @@ export const categorizedLessons = state => {
byCategory[category].levels.push(stageLevels);
});

// Peer reviews get their own category, but these levels/lessson are stored
// separately from our other levels/lessons in redux (since they're slightly
// different)
if (state.peerReviewStage) {
byCategory['Peer Review'] = {
category: 'Peer Review',
lessons: [peerReviewLesson(state)],
levels: [peerReviewLevels(state)]
};
}

// We want to return an array of categories
return _.values(byCategory);
};
Expand Down Expand Up @@ -365,6 +409,9 @@ export const progressionsFromLevels = levels => {
/* start-test-block */
// export private function(s) to expose to unit testing
export const __testonly__ = {
bestResultLevelId
bestResultLevelId,
peerReviewLesson,
peerReviewLevels,
PEER_REVIEW_ID
};
/* end-test-block */
2 changes: 1 addition & 1 deletion apps/src/gamelab/GameLabSprite.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ module.exports.createSprite = function (x, y, width, height) {
// frame, which will cause the animation to continue on the next update().
// If the animation is non-looping and is stopped at the last frame
// we also rewind the animation to the beginning.
if (!s.animation.looping && s.animation.getFrame() === s.animation.images.length - 1) {
if (!s.animation.looping && !s.animation.playing && s.animation.getFrame() === s.animation.images.length - 1) {
s.animation.rewind();
}
s.animation.play();
Expand Down
82 changes: 82 additions & 0 deletions apps/src/templates/progress/FocusAreaIndicator.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* A component that adds a ribbon to the side of your row to indicate that it is
* a focus area. Note: This is English only.
*/

import React from 'react';
import Radium from 'radium';
import ReactTooltip from 'react-tooltip';
import FontAwesome from '@cdo/apps/templates/FontAwesome';
import color from "@cdo/apps/util/color";

const styles = {
main: {
display: 'inline-block',
position: 'absolute',
right: 0,
top: 0,
whiteSpace: 'nowrap'
},
arrowContainer: {
display: 'inline-block',
position: 'relative',
top: 10
},
leftArrow: {
display: 'inline-block',
width: 0,
height: 0,
borderStyle: 'solid',
borderWidth: '17px 20px 17px',
borderColor: `transparent ${color.cyan} transparent transparent`
},
focusArea: {
display: 'inline-block',
backgroundColor: color.cyan,
color: color.white,
height: 34,
lineHeight: '34px',
position: 'relative',
top: -3,
},
text: {
display: 'inline-block'
},
focusAreaIcon: {
display: 'inline-block',
color: color.white,
lineHeight: '13px',
padding: 5,
marginLeft: 5,
marginRight: 5,
borderRadius: 4,
':hover': {
backgroundColor: color.default_blue,
}
}
};

const FocusAreaIndicator = () => (
<div style={styles.main}>
<div style={styles.arrowContainer}>
<div style={styles.leftArrow}/>
</div>
<div style={styles.focusArea}>
<div style={styles.text}>Focus Area</div>
<a href={window.location.pathname + "/preview-assignments"} >
<div style={styles.focusAreaIcon} data-tip data-for="focus-area">
<FontAwesome icon="pencil"/>
</div>
</a>
</div>
<ReactTooltip
id="focus-area"
role="tooltip"
effect="solid"
>
Click to change your focus area.
</ReactTooltip>
</div>
);

export default Radium(FocusAreaIndicator);
12 changes: 6 additions & 6 deletions apps/src/templates/progress/ProgressBubble.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ const ProgressBubble = React.createClass({
},

render() {
const { number, status, url, disabled, levelName, levelIcon } = this.props;
const { number, status, url, levelName, levelIcon } = this.props;

const disabled = this.props.disabled || levelIcon === 'lock';

const style = {
...styles.main,
Expand All @@ -66,10 +68,11 @@ const ProgressBubble = React.createClass({
href = url + location.search;
}

let bubble = (
const interior = levelIcon === 'lock' ? <FontAwesome icon="lock"/> : number;

let bubble = (
<div style={style} data-tip data-for={url} aria-describedby={url}>
{number}
{interior}
<ReactTooltip
id={url}
role="tooltip"
Expand All @@ -79,11 +82,8 @@ const ProgressBubble = React.createClass({
{levelName}
</ReactTooltip>
</div>

);



// If we have an href, wrap in an achor tag
if (href) {
bubble = (
Expand Down
7 changes: 4 additions & 3 deletions apps/src/templates/progress/ProgressBubbleSet.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ const ProgressBubbleSet = React.createClass({
url: PropTypes.string
})
).isRequired,
disabled: PropTypes.bool.isRequired
disabled: PropTypes.bool.isRequired,
style: PropTypes.object,
},

getIcon(level) {
Expand All @@ -56,10 +57,10 @@ const ProgressBubbleSet = React.createClass({
},

render() {
const { start, levels, disabled } = this.props;
const { start, levels, disabled, style } = this.props;

return (
<div style={styles.main}>
<div style={{...styles.main, ...style}}>
{levels.map((level, index) => (
<div
style={styles.withBackground}
Expand Down
3 changes: 3 additions & 0 deletions apps/src/templates/progress/ProgressLesson.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import i18n from '@cdo/locale';
import { lessonIsVisible, lessonIsLockedForAllStudents } from './progressHelpers';
import { LevelStatus } from '@cdo/apps/util/sharedConstants';
import ProgressLessonTeacherInfo from './ProgressLessonTeacherInfo';
import FocusAreaIndicator from './FocusAreaIndicator';

const styles = {
outer: {
position: 'relative',
display: 'table',
width: '100%',
marginBottom: 12,
Expand Down Expand Up @@ -154,6 +156,7 @@ const ProgressLesson = React.createClass({
<ProgressLessonTeacherInfo lesson={lesson}/>
</div>
}
{lesson.isFocusArea && <FocusAreaIndicator/>}
</div>
);
}
Expand Down

0 comments on commit d0bac56

Please sign in to comment.