Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Progress redux stage to lesson #40686

Merged
merged 7 commits into from
May 21, 2021
Merged
8 changes: 4 additions & 4 deletions apps/src/code-studio/components/TeacherContentToggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,20 +126,20 @@ export const mapStateToProps = state => {

let isLockedLesson = false;
let isHiddenLesson = false;
const {currentStageId} = state.progress;
const {currentLessonId} = state.progress;
if (viewAs === ViewType.Student) {
const {selectedSectionId} = state.teacherSections;

isLockedLesson = lessonIsLockedForAllStudents(currentStageId, state);
isLockedLesson = lessonIsLockedForAllStudents(currentLessonId, state);
isHiddenLesson = isLessonHiddenForSection(
state.hiddenLesson,
selectedSectionId,
currentStageId
currentLessonId
);
} else if (!state.verifiedTeacher.isVerified) {
// if not-authorized teacher
isLockedLesson = state.progress.stages.some(
lesson => lesson.id === currentStageId && lesson.lockable
lesson => lesson.id === currentLessonId && lesson.lockable
);
}

Expand Down
4 changes: 2 additions & 2 deletions apps/src/code-studio/components/progress/LessonProgress.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ const styles = {
export const UnconnectedLessonProgress = LessonProgress;

export default connect(state => ({
levels: levelsForLessonId(state.progress, state.progress.currentStageId),
levels: levelsForLessonId(state.progress, state.progress.currentLessonId),
lessonExtrasUrl: lessonExtrasUrl(
state.progress,
state.progress.currentStageId
state.progress.currentLessonId
),
isLessonExtras: state.progress.isLessonExtras,
currentPageNumber: state.progress.currentPageNumber,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import lessonLock from '../../lessonLockRedux';
import progress, {
initProgress,
mergeResults,
setStageExtrasEnabled
setLessonExtrasEnabled
} from '../../progressRedux';
import {TestResults} from '@cdo/apps/constants';

Expand Down Expand Up @@ -119,7 +119,7 @@ export default storybook => {
results[100] = TestResults.ALL_PASS;
}
store.dispatch(mergeResults(results));
store.dispatch(setStageExtrasEnabled(showStageExtras));
store.dispatch(setLessonExtrasEnabled(showStageExtras));
return store;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const initialState = {
levels: []
}
],
focusAreaStageIds: [],
focusAreaLessonIds: [],
isSummaryView: false,
professionalLearningCourse: false
}
Expand Down
4 changes: 2 additions & 2 deletions apps/src/code-studio/components/progress/TeacherPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ViewAsToggle from './ViewAsToggle';
import FontAwesome from '@cdo/apps/templates/FontAwesome';
import {fullyLockedLessonMapping} from '../../lessonLockRedux';
import {ViewType} from '../../viewAsRedux';
import {hasLockableStages} from '../../progressRedux';
import {hasLockableLessons} from '../../progressRedux';
import {pageTypes} from '@cdo/apps/templates/teacherDashboard/teacherSectionsRedux';
import StudentTable, {studentShape} from './StudentTable';
import {teacherDashboardUrl} from '@cdo/apps/templates/teacherDashboard/urlHelpers';
Expand Down Expand Up @@ -267,7 +267,7 @@ export default connect(state => {

// Pretend we don't have lockable lessons if we're not authorized to see them
const scriptHasLockableStages =
lockableAuthorized && hasLockableStages(state.progress);
lockableAuthorized && hasLockableLessons(state.progress);

return {
viewAs: state.viewAs,
Expand Down
4 changes: 2 additions & 2 deletions apps/src/code-studio/progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
setIsHocScript,
setIsAge13Required,
setStudentDefaultsSummaryView,
setStageExtrasEnabled,
setLessonExtrasEnabled,
queryUserProgress as reduxQueryUserProgress,
useDbProgress
} from './progressRedux';
Expand Down Expand Up @@ -124,7 +124,7 @@ progress.generateStageProgress = function(
store.dispatch(setIsHocScript(isHocScript));

if (lessonExtrasEnabled) {
store.dispatch(setStageExtrasEnabled(true));
store.dispatch(setLessonExtrasEnabled(true));
}

return populateProgress(store, signedIn, progressData, name);
Expand Down
112 changes: 57 additions & 55 deletions apps/src/code-studio/progressRedux.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ const SET_IS_AGE_13_REQUIRED = 'progress/SET_IS_AGE_13_REQUIRED';
const SET_IS_SUMMARY_VIEW = 'progress/SET_IS_SUMMARY_VIEW';
const SET_STUDENT_DEFAULTS_SUMMARY_VIEW =
'progress/SET_STUDENT_DEFAULTS_SUMMARY_VIEW';
const SET_CURRENT_STAGE_ID = 'progress/SET_CURRENT_STAGE_ID';
const SET_CURRENT_LESSON_ID = 'progress/SET_CURRENT_LESSON_ID';
const SET_SCRIPT_COMPLETED = 'progress/SET_SCRIPT_COMPLETED';
const SET_STAGE_EXTRAS_ENABLED = 'progress/SET_STAGE_EXTRAS_ENABLED';
const SET_LESSON_EXTRAS_ENABLED = 'progress/SET_LESSON_EXTRAS_ENABLED';
const USE_DB_PROGRESS = 'progress/USE_DB_PROGRESS';
const OVERWRITE_RESULTS = 'progress/OVERWRITE_RESULTS';

Expand All @@ -41,7 +41,7 @@ const PEER_REVIEW_ID = -1;
const initialState = {
// These first fields never change after initialization
currentLevelId: null,
currentStageId: null,
currentLessonId: null,
professionalLearningCourse: null,
// used on multi-page assessments
saveAnswersBeforeNavigation: null,
Expand All @@ -60,7 +60,7 @@ const initialState = {
// levelResults is a map of levelId -> TestResult
// note: eventually, we expect usage of this field to be replaced with scriptProgress
levelResults: {},
focusAreaStageIds: [],
focusAreaLessonIds: [],
peerReviewLessonInfo: null,
peerReviewsPerformed: [],
showTeacherInfo: false,
Expand All @@ -85,17 +85,18 @@ const initialState = {
*/
export default function reducer(state = initialState, action) {
if (action.type === INIT_PROGRESS) {
let stages = action.stages;
// Re-initializing with full set of stages shouldn't blow away currentStageId
const currentStageId =
state.currentStageId || (stages.length === 1 ? stages[0].id : undefined);
let lessons = action.stages;
// Re-initializing with full set of lessons shouldn't blow away currentLessonId
const currentLessonId =
state.currentLessonId ||
(lessons.length === 1 ? lessons[0].id : undefined);
// extract fields we care about from action
return {
...state,
currentLevelId: action.currentLevelId,
professionalLearningCourse: action.professionalLearningCourse,
saveAnswersBeforeNavigation: action.saveAnswersBeforeNavigation,
stages: processedStages(stages, action.professionalLearningCourse),
stages: processedLessons(lessons, action.professionalLearningCourse),
lessonGroups: action.lessonGroups,
peerReviewLessonInfo: action.peerReviewLessonInfo,
scriptId: action.scriptId,
Expand All @@ -105,7 +106,7 @@ export default function reducer(state = initialState, action) {
scriptStudentDescription: action.scriptStudentDescription,
betaTitle: action.betaTitle,
courseId: action.courseId,
currentStageId,
currentLessonId,
hasFullProgress: action.isFullProgress,
isLessonExtras: action.isLessonExtras,
currentPageNumber: action.currentPageNumber
Expand Down Expand Up @@ -176,7 +177,7 @@ export default function reducer(state = initialState, action) {
return {
...state,
changeFocusAreaPath: action.changeFocusAreaPath,
focusAreaStageIds: action.focusAreaStageIds
focusAreaLessonIds: action.focusAreaLessonIds
};
}

Expand Down Expand Up @@ -231,17 +232,17 @@ export default function reducer(state = initialState, action) {
};
}

if (action.type === SET_CURRENT_STAGE_ID) {
// if we already have a currentStageId, that means we're on a puzzle page,
// and we want currentStageId to remain the same (rather than reflecting
// the last stage the user has made progress on).
if (state.currentStageId) {
if (action.type === SET_CURRENT_LESSON_ID) {
// if we already have a currentLessonId, that means we're on a puzzle page,
// and we want currentLessonId to remain the same (rather than reflecting
// the last lesson the user has made progress on).
if (state.currentLessonId) {
return state;
}

return {
...state,
currentStageId: action.stageId
currentLessonId: action.lessonId
};
}

Expand All @@ -252,10 +253,10 @@ export default function reducer(state = initialState, action) {
};
}

if (action.type === SET_STAGE_EXTRAS_ENABLED) {
if (action.type === SET_LESSON_EXTRAS_ENABLED) {
return {
...state,
stageExtrasEnabled: action.stageExtrasEnabled
stageExtrasEnabled: action.lessonExtrasEnabled
};
}

Expand Down Expand Up @@ -300,7 +301,7 @@ function bestResultLevelId(levelIds, progressData) {
* - Adds 'stageNumber' field for non-PLC lessons which
* are not lockable or have a lesson plan
*/
export function processedStages(lessons, isPlc) {
export function processedLessons(lessons, isPlc) {
let numLessonsWithLessonPlan = 0;

return lessons.map(lesson => {
Expand Down Expand Up @@ -356,9 +357,9 @@ const userProgressFromServer = (state, dispatch, userId = null) => {
dispatch(showTeacherInfo());
}

if (data.focusAreaStageIds) {
if (data.focusAreaLessonIds) {
dispatch(
updateFocusArea(data.changeFocusAreaPath, data.focusAreaStageIds)
updateFocusArea(data.changeFocusAreaPath, data.focusAreaLessonIds)
);
}

Expand Down Expand Up @@ -386,7 +387,7 @@ const userProgressFromServer = (state, dispatch, userId = null) => {
}

if (data.current_stage) {
dispatch(setCurrentStageId(data.current_stage));
dispatch(setCurrentLessonId(data.current_stage));
}
}
});
Expand Down Expand Up @@ -464,10 +465,10 @@ export const mergePeerReviewProgress = peerReviewsPerformed => ({
peerReviewsPerformed
});

export const updateFocusArea = (changeFocusAreaPath, focusAreaStageIds) => ({
export const updateFocusArea = (changeFocusAreaPath, focusAreaLessonIds) => ({
type: UPDATE_FOCUS_AREAS,
changeFocusAreaPath,
focusAreaStageIds
focusAreaLessonIds
});

export const showTeacherInfo = () => ({type: SHOW_TEACHER_INFO});
Expand All @@ -489,14 +490,14 @@ export const setStudentDefaultsSummaryView = studentDefaultsSummaryView => ({
type: SET_STUDENT_DEFAULTS_SUMMARY_VIEW,
studentDefaultsSummaryView
});
export const setCurrentStageId = stageId => ({
type: SET_CURRENT_STAGE_ID,
stageId
export const setCurrentLessonId = lessonId => ({
type: SET_CURRENT_LESSON_ID,
lessonId
});
export const setScriptCompleted = () => ({type: SET_SCRIPT_COMPLETED});
export const setStageExtrasEnabled = stageExtrasEnabled => ({
type: SET_STAGE_EXTRAS_ENABLED,
stageExtrasEnabled
export const setLessonExtrasEnabled = lessonExtrasEnabled => ({
type: SET_LESSON_EXTRAS_ENABLED,
lessonExtrasEnabled
});

export const queryUserProgress = userId => (dispatch, getState) => {
Expand All @@ -506,25 +507,25 @@ export const queryUserProgress = userId => (dispatch, getState) => {

// Selectors

// Do we have one or more lockable stages
export const hasLockableStages = state =>
state.stages.some(stage => stage.lockable);
// Do we have one or more lockable lessons
export const hasLockableLessons = state =>
state.stages.some(lesson => lesson.lockable);

export const hasGroups = state => Object.keys(groupedLessons(state)).length > 1;

/**
* Extract the relevant portions of a particular lesson/stage from the store.
* Extract the relevant portions of a particular lesson/lesson 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
* @param {number} lessonIndex - The index into our lessons we care about
* @returns {Lesson}
*/
const lessonFromStageAtIndex = (state, stageIndex) => ({
...lessonFromStage(state.stages[stageIndex]),
isFocusArea: state.focusAreaStageIds.includes(state.stages[stageIndex].id)
const lessonFromLessonAtIndex = (state, lessonIndex) => ({
...lessonFromLesson(state.stages[lessonIndex]),
isFocusArea: state.focusAreaLessonIds.includes(state.stages[lessonIndex].id)
});
const lessonFromStage = stage =>
_.pick(stage, [
const lessonFromLesson = lesson =>
_.pick(lesson, [
'name',
'id',
'lockable',
Expand All @@ -535,15 +536,15 @@ const lessonFromStage = stage =>
'description_teacher'
]);
export const lessons = state =>
state.stages.map((_, index) => lessonFromStageAtIndex(state, index));
state.stages.map((_, index) => lessonFromLessonAtIndex(state, index));

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

/**
* Get level data for all lessons/stages
* Get level data for all lessons/lessons
*/
export const levelsByLesson = ({
stages,
Expand All @@ -624,19 +625,19 @@ export const levelsByLesson = ({
levelPairing,
currentLevelId
}) =>
stages.map(stage =>
stage.levels.map(level => {
stages.map(lesson =>
lesson.levels.map(level => {
let statusLevel = levelWithProgress(
{levelResults, scriptProgress, levelPairing, currentLevelId},
level,
stage.lockable
lesson.lockable
);
if (statusLevel.sublevels) {
statusLevel.sublevels = level.sublevels.map(sublevel =>
levelWithProgress(
{levelResults, scriptProgress, levelPairing, currentLevelId},
sublevel,
stage.lockable
lesson.lockable
)
);
}
Expand All @@ -645,18 +646,19 @@ export const levelsByLesson = ({
);

/**
* Get data for a particular lesson/stage
* Get data for a particular lesson/lesson
*/
export const levelsForLessonId = (state, lessonId) => {
const lesson = state.stages.find(stage => stage.id === lessonId);
const lesson = state.stages.find(lesson => lesson.id === lessonId);
return lesson.levels.map(level =>
levelWithProgress(state, level, lesson.lockable)
);
};

export const lessonExtrasUrl = (state, stageId) =>
export const lessonExtrasUrl = (state, lessonId) =>
state.stageExtrasEnabled
? state.stages.find(stage => stage.id === stageId).lesson_extras_level_url
? state.stages.find(lesson => lesson.id === lessonId)
.lesson_extras_level_url
: '';

export const isPerfect = (state, levelId) =>
Expand Down Expand Up @@ -691,7 +693,7 @@ export const groupedLessons = (state, includeBonusLevels = false) => {

state.stages.forEach((lesson, index) => {
const group = lesson.lesson_group_display_name;
const lessonAtIndex = lessonFromStageAtIndex(state, index);
const lessonAtIndex = lessonFromLessonAtIndex(state, index);
let lessonLevels = allLevels[index];
if (!includeBonusLevels) {
lessonLevels = lessonLevels.filter(level => !level.bonus);
Expand Down