Skip to content

Commit

Permalink
Merge pull request #13485 from code-dot-org/lockableRedesign
Browse files Browse the repository at this point in the history
Lockable stages with progress redesign
  • Loading branch information
Bjvanminnen committed Mar 1, 2017
2 parents 0681c44 + 3bb0e37 commit 3a8e19b
Show file tree
Hide file tree
Showing 24 changed files with 699 additions and 241 deletions.
6 changes: 3 additions & 3 deletions apps/src/code-studio/components/TeacherContentToggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import $ from 'jquery';
import React, { PropTypes } from 'react';
import Radium from 'radium';
import { connect } from 'react-redux';
import { ViewType, fullyLockedStageMapping } from '../stageLockRedux';
import { ViewType } from '../stageLockRedux';
import { lessonIsLockedForAllStudents } from '@cdo/apps/templates/progress/progressHelpers';
import { isHiddenForSection } from '../hiddenStageRedux';

const styles = {
Expand Down Expand Up @@ -113,8 +114,7 @@ export default connect(state => {
const { currentStageId } = state.progress;
const { selectedSectionId } = state.sections;

const fullyLocked = fullyLockedStageMapping(state.stageLock.stagesBySectionId[selectedSectionId]);
isLockedStage = !!fullyLocked[currentStageId];
isLockedStage = lessonIsLockedForAllStudents(currentStageId, state);
isHiddenStage = isHiddenForSection(state.hiddenStage, selectedSectionId, currentStageId);
}

Expand Down
29 changes: 18 additions & 11 deletions apps/src/code-studio/components/progress/ProgressDot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React from 'react';
import ReactDOM from 'react-dom';
import Radium from 'radium';
import { connect } from 'react-redux';

import _ from 'lodash';
import { levelProgressShape } from './types';
import { saveAnswersAndNavigate } from '../../levels/saveAnswers';
import color from "../../../util/color";
import color from '@cdo/apps/util/color';
import progressStyles, { createOutline } from './progressStyles';
import { LevelStatus, LevelKind } from '@cdo/apps/util/sharedConstants';

Expand All @@ -15,40 +15,44 @@ const dotSize = 24;
* Styles to color bubbles
*/
export const BUBBLE_COLORS = {
submitted: {
[LevelStatus.submitted]: {
color: color.white,
backgroundColor: color.level_submitted
},
perfect: {
[LevelStatus.perfect]: {
color: color.white,
backgroundColor: color.level_perfect
},
passed: {
[LevelStatus.passed]: {
color: color.white,
backgroundColor: color.level_passed
},
attempted: {
[LevelStatus.attempted]: {
color: color.charcoal,
backgroundColor: color.level_attempted
},
not_tried: {
[LevelStatus.not_tried]: {
color: color.charcoal,
backgroundColor: color.level_not_tried
},
review_rejected: {
[LevelStatus.review_rejected]: {
color: color.white,
backgroundColor: color.level_review_rejected
},
review_accepted: {
[LevelStatus.review_accepted]: {
color: color.white,
backgroundColor: color.level_perfect
},
dots_disabled: {
[LevelStatus.dots_disabled]: {
color: color.charcoal,
backgroundColor: color.lightest_gray
},
multi_level: {
color: color.charcoal
},
[LevelStatus.locked]: {
color: color.charcoal,
backgroundColor: color.white
}
};

Expand Down Expand Up @@ -130,7 +134,10 @@ const styles = {
}
}
},
status: BUBBLE_COLORS
// In our redesign we want locked levels to have a white background, but we
// don't want this in non-redesigned dots. Accomplish this not having a
// bubble color for locked.
status: _.omit(BUBBLE_COLORS, LevelStatus.locked)
};

// Longer term, I'd like the server to provide us an icon type, instead of a
Expand Down
27 changes: 9 additions & 18 deletions apps/src/code-studio/components/progress/StatusProgressDot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import ProgressDot from './ProgressDot';
import { levelProgressShape } from './types';
import { ViewType, fullyLockedStageMapping } from '../../stageLockRedux';
import { ViewType } from '../../stageLockRedux';
import { LevelStatus } from '@cdo/apps/util/sharedConstants';
import { SignInState, statusForLevel } from '../../progressRedux';
import { lessonIsLockedForAllStudents } from '@cdo/apps/templates/progress/progressHelpers';

/**
* Wrapper around ProgressDot that owns determining the correct status for the
Expand All @@ -18,41 +19,31 @@ export const StatusProgressDot = React.createClass({
stageId: PropTypes.number,

// redux provided
currentSection: PropTypes.objectOf(
PropTypes.arrayOf(
PropTypes.shape({
locked: PropTypes.bool.isRequired,
name: PropTypes.string.isRequired,
readonly_answers: PropTypes.bool.isRequired,
user_level_data: PropTypes.object.isRequired
})
)
),
viewAs: PropTypes.oneOf(Object.values(ViewType)).isRequired,
postMilestoneDisabled: PropTypes.bool.isRequired,
signInState: PropTypes.oneOf(Object.values(SignInState)).isRequired,
levelProgress: PropTypes.object.isRequired
levelProgress: PropTypes.object.isRequired,
lessonIsLockedForAllStudents: PropTypes.func.isRequired
},

render() {
const {
level,
courseOverviewPage,
stageId,
currentSection,
viewAs,
postMilestoneDisabled,
signInState,
levelProgress
levelProgress,
lessonIsLockedForAllStudents
} = this.props;

let status = statusForLevel(level, levelProgress);

// If we're a teacher viewing as a student, we want to render lockable stages
// to have a lockable item only if the stage is fully locked.
if (stageId !== undefined && viewAs === ViewType.Student) {
const fullyLocked = fullyLockedStageMapping(currentSection);
if (!!fullyLocked[stageId]) {
if (lessonIsLockedForAllStudents(stageId)) {
status = LevelStatus.locked;
}
}
Expand Down Expand Up @@ -87,7 +78,7 @@ export default connect(state => ({
// white) until we know whether we're signed in or not.
postMilestoneDisabled: state.progress.postMilestoneDisabled,
signInState: state.progress.signInState,
currentSection: state.stageLock.stagesBySectionId[state.sections.selectedSectionId],
viewAs: state.stageLock.viewAs,
levelProgress: state.progress.levelProgress
levelProgress: state.progress.levelProgress,
lessonIsLockedForAllStudents: lessonId => lessonIsLockedForAllStudents(lessonId, state)
}))(StatusProgressDot);
10 changes: 5 additions & 5 deletions apps/src/code-studio/teacher.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import ScriptTeacherPanel from './components/progress/ScriptTeacherPanel';
import SectionSelector from './components/progress/SectionSelector';
import ViewAsToggle from './components/progress/ViewAsToggle';
import TeacherContentToggle from './components/TeacherContentToggle';
import { fullyLockedStageMapping, ViewType, setViewType } from './stageLockRedux';
import { ViewType, setViewType } from './stageLockRedux';
import { lessonIsLockedForAllStudents } from '@cdo/apps/templates/progress/progressHelpers';
import { setSections, selectSection } from './sectionsRedux';
import { getHiddenStages } from './hiddenStageRedux';
import commonMsg from '@cdo/locale';
Expand Down Expand Up @@ -135,11 +136,10 @@ function renderIntoLessonTeacherPanel() {
if (stageLockedText) {
const state = store.getState();

const { currentStageId } = state.progress;
const { selectedSectionId } = state.sections;
const fullyLocked = fullyLockedStageMapping(state.stageLock.stagesBySectionId[selectedSectionId]);

if (fullyLocked[currentStageId]) {

const { currentStageId } = state.progress;
if (lessonIsLockedForAllStudents(currentStageId, state)) {
$(stageLockedText).text(commonMsg.stageLocked());
} else {
$(stageLockedText).text(commonMsg.stageNotFullyLocked());
Expand Down
40 changes: 28 additions & 12 deletions apps/src/templates/progress/ProgressBubble.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React, { PropTypes } from 'react';
import Radium from 'radium';
import color from "@cdo/apps/util/color";
import { LevelStatus } from '@cdo/apps/util/sharedConstants';

// TODO - not sure I like these bubble color styles being keyed by these strings.
// In a future PR, share with ProgressDot, likely by using an Enum of different
// allowable values.
import { BUBBLE_COLORS } from '@cdo/apps/code-studio/components/progress/ProgressDot';

export const DOT_SIZE = 30;
Expand All @@ -28,6 +26,8 @@ const styles = {
marginTop: 5,
marginBottom: 5,
transition: 'background-color .2s ease-out, border-color .2s ease-out, color .2s ease-out',
},
enabled: {
':hover': {
textDecoration: 'none',
color: color.white,
Expand All @@ -40,24 +40,40 @@ const ProgressBubble = React.createClass({
propTypes: {
number: PropTypes.number.isRequired,
status: PropTypes.oneOf(Object.keys(BUBBLE_COLORS)).isRequired,
url: PropTypes.string
url: PropTypes.string,
disabled: PropTypes.bool.isRequired
},

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

const style = {
...styles.main,
...BUBBLE_COLORS[status]
...(!disabled && styles.enabled),
...(BUBBLE_COLORS[disabled ? LevelStatus.not_tried : status])
};

return (
<a href={url ? url + location.search : undefined}>
<div style={style}>
{number}
</div>
</a>
let href = '';
if (!disabled && url) {
href = url + location.search;
}

let bubble = (
<div style={style}>
{number}
</div>
);

// If we have an href, wrap in an achor tag
if (href) {
bubble = (
<a href={href}>
{bubble}
</a>
);
}

return bubble;
}
});

Expand Down
16 changes: 15 additions & 1 deletion apps/src/templates/progress/ProgressBubble.story.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import ProgressBubble from './ProgressBubble';
import { BUBBLE_COLORS } from '@cdo/apps/code-studio/components/progress/ProgressDot';
import { LevelStatus } from '@cdo/apps/util/sharedConstants';

const statuses = Object.keys(BUBBLE_COLORS);

Expand All @@ -15,14 +16,27 @@ export default storybook => {
number={3}
status={status}
url="/foo/bar"
disabled={false}
/>
)
})).concat([{
name:'bubble with no url',
story: () => (
<ProgressBubble
number={3}
status="perfect"
status={LevelStatus.perfect}
disabled={false}
/>
)
}, {
name:'disabled bubble',
description: 'Should not be clickable or show progress',
story: () => (
<ProgressBubble
number={3}
status={LevelStatus.perfect}
url="/foo/bar"
disabled={true}
/>
)
}])
Expand Down
6 changes: 4 additions & 2 deletions apps/src/templates/progress/ProgressBubbleSet.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ const ProgressBubbleSet = React.createClass({
level: PropTypes.string,
url: PropTypes.string
})
).isRequired
).isRequired,
disabled: PropTypes.bool.isRequired
},

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

return (
<div style={styles.main}>
Expand All @@ -69,6 +70,7 @@ const ProgressBubbleSet = React.createClass({
number={start + index}
status={level.status}
url={level.url}
disabled={disabled}
/>
</div>
</div>
Expand Down
Loading

0 comments on commit 3a8e19b

Please sign in to comment.