diff --git a/public/assets/mockChapter0.txt b/public/assets/mockChapter0.txt index b22cc9febf..27ba58a9dc 100644 --- a/public/assets/mockChapter0.txt +++ b/public/assets/mockChapter0.txt @@ -4,9 +4,9 @@ objectives finish gameStartActions - // replace 173 with assessment id - show_dialogue(welcome) if userstate.assessments.173 - show_dialogue(unwelcome) if !userstate.assessments.173 + // replace S0 with assessment number + show_dialogue(welcome) if userstate.assessments.S0 + show_dialogue(unwelcome) if !userstate.assessments.S0 checkpointCompleteActions show_dialogue(done) @@ -96,8 +96,8 @@ dialogues 1 @scottie, sad You haven't finished assessment - Finish assessment 173 first and come back? - navigate_to_assessment(173) + Finish assessment S0 first and come back? + navigate_to_assessment(S0) goto 2 2 @scottie @@ -113,7 +113,7 @@ dialogues Hmmm update_assessment_status*() Let me check - goto 1 if !userstate.assessments.173 else 3 + goto 1 if !userstate.assessments.S0 else 3 what, What should I do now, Scottie? @you diff --git a/src/commons/application/actions/__tests__/SessionActions.ts b/src/commons/application/actions/__tests__/SessionActions.ts index cf65144525..b2fdd8a26b 100644 --- a/src/commons/application/actions/__tests__/SessionActions.ts +++ b/src/commons/application/actions/__tests__/SessionActions.ts @@ -264,6 +264,7 @@ test('setAssessmentConfigurations generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -275,6 +276,7 @@ test('setAssessmentConfigurations generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -286,6 +288,7 @@ test('setAssessmentConfigurations generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -714,6 +717,7 @@ test('updateAssessmentTypes generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -725,6 +729,7 @@ test('updateAssessmentTypes generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -736,6 +741,7 @@ test('updateAssessmentTypes generates correct action object', () => { isManuallyGraded: false, isGradingAutoPublished: true, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -747,6 +753,7 @@ test('updateAssessmentTypes generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -758,6 +765,7 @@ test('updateAssessmentTypes generates correct action object', () => { isManuallyGraded: false, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 0, @@ -769,6 +777,7 @@ test('updateAssessmentTypes generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, @@ -789,6 +798,7 @@ test('deleteAssessmentConfig generates correct action object', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, diff --git a/src/commons/application/reducers/__tests__/SessionReducer.ts b/src/commons/application/reducers/__tests__/SessionReducer.ts index 8a589c4aad..d95a3e52a4 100644 --- a/src/commons/application/reducers/__tests__/SessionReducer.ts +++ b/src/commons/application/reducers/__tests__/SessionReducer.ts @@ -147,6 +147,7 @@ test('SET_ASSESSMENT_CONFIGURATIONS works correctly', () => { isManuallyGraded: false, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false }, @@ -161,6 +162,7 @@ test('SET_ASSESSMENT_CONFIGURATIONS works correctly', () => { isManuallyGraded: false, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false }, @@ -175,6 +177,7 @@ test('SET_ASSESSMENT_CONFIGURATIONS works correctly', () => { isManuallyGraded: false, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false } diff --git a/src/commons/assessment/AssessmentTypes.ts b/src/commons/assessment/AssessmentTypes.ts index c3d5cecbf4..2bd726f9b3 100644 --- a/src/commons/assessment/AssessmentTypes.ts +++ b/src/commons/assessment/AssessmentTypes.ts @@ -92,6 +92,7 @@ export type Assessment = { globalDeployment?: Library; // For mission control graderDeployment?: Library; // For mission control hasTokenCounter?: boolean; + isMinigame?: boolean; id: number; longSummary: string; missionPDF: string; @@ -105,6 +106,7 @@ export type AssessmentConfiguration = { isManuallyGraded: boolean; isGradingAutoPublished: boolean; displayInDashboard: boolean; + isMinigame: boolean; hoursBeforeEarlyXpDecay: number; earlySubmissionXp: number; hasTokenCounter: boolean; diff --git a/src/commons/assessment/__tests__/Assessment.tsx b/src/commons/assessment/__tests__/Assessment.tsx index 322d2386dd..e2f628e30e 100644 --- a/src/commons/assessment/__tests__/Assessment.tsx +++ b/src/commons/assessment/__tests__/Assessment.tsx @@ -17,6 +17,7 @@ const mockAssessmentConfig: AssessmentConfiguration = { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, diff --git a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx index cc3723a158..20138018e5 100644 --- a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx +++ b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx @@ -94,6 +94,7 @@ const AssessmentWorkspace: React.FC = props => { const [isSaving, setIsSaving] = useState(false); const [showResetTemplateOverlay, setShowResetTemplateOverlay] = useState(false); const [sessionId, setSessionId] = useState(''); + const [isSubmitted, setIsSubmitted] = useState(false); const { isMobileBreakpoint } = useResponsive(); const assessment = useTypedSelector(state => state.session.assessments[props.assessmentId]); @@ -600,6 +601,10 @@ const AssessmentWorkspace: React.FC = props => { setSelectedTab(SideContentType.questionOverview); }; const onClickReturn = () => navigate(listingPath); + const onClickSubmit = () => { + dispatch(SessionActions.submitAssessment(assessment.id)); + setIsSubmitted(true); + }; const onClickSave = () => { if (isSaving) return; @@ -664,8 +669,14 @@ const AssessmentWorkspace: React.FC = props => { ? onClickProgress(onClickReturn, question, editorTestcases, isBlocked) : onClickReturn } + onClickSubmit={ + question.blocking + ? onClickProgress(onClickSubmit, question, editorTestcases, isBlocked) + : onClickSubmit + } questionProgress={questionProgress} key="next_question" + submitOnFinish={assessment.isMinigame} /> ); @@ -834,6 +845,18 @@ const AssessmentWorkspace: React.FC = props => { ); + const submissionOverlay = ( + + + + + + ); + const closeOverlay = () => setShowResetTemplateOverlay(false); const resetTemplateOverlay = ( = props => { }; return (
+ {submissionOverlay} {overlay} {resetTemplateOverlay} {!isMobileBreakpoint ? ( diff --git a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx index df1f2b01c8..311db2ed35 100644 --- a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx +++ b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx @@ -21,6 +21,7 @@ const defaultProps = assertType()({ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 48, diff --git a/src/commons/controlBar/ControlBarNextButton.tsx b/src/commons/controlBar/ControlBarNextButton.tsx index 2723e18e72..6e4d124876 100644 --- a/src/commons/controlBar/ControlBarNextButton.tsx +++ b/src/commons/controlBar/ControlBarNextButton.tsx @@ -3,22 +3,29 @@ import React from 'react'; import ControlButton from '../ControlButton'; import { ControlBarReturnToAcademyButton } from './ControlBarReturnToAcademyButton'; +import { ControlBarSubmit } from './ControlBarSubmit'; type ControlBarNextButtonProps = DispatchProps & StateProps; type DispatchProps = { onClickNext?(): any; onClickReturn?(): any; + onClickSubmit?(): any; }; type StateProps = { key: string; questionProgress: [number, number] | null; + submitOnFinish?: boolean; }; export const ControlBarNextButton: React.FC = props => { return props.questionProgress![0] === props.questionProgress![1] ? ( - + props.submitOnFinish ? ( + + ) : ( + + ) ) : ( = ({ onClick }) => { + return ( + + ); +}; diff --git a/src/commons/mocks/AssessmentMocks.ts b/src/commons/mocks/AssessmentMocks.ts index deda0f8cba..2619f87642 100644 --- a/src/commons/mocks/AssessmentMocks.ts +++ b/src/commons/mocks/AssessmentMocks.ts @@ -21,6 +21,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -32,6 +33,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -43,6 +45,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: false, isGradingAutoPublished: true, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -54,6 +57,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: true, @@ -65,6 +69,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -78,6 +83,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -89,6 +95,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -100,6 +107,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, diff --git a/src/commons/profile/__tests__/Profile.tsx b/src/commons/profile/__tests__/Profile.tsx index 3afa98e90b..816aa4af88 100644 --- a/src/commons/profile/__tests__/Profile.tsx +++ b/src/commons/profile/__tests__/Profile.tsx @@ -26,6 +26,7 @@ const assessmentConfigurations: AssessmentConfiguration[] = [ isManuallyGraded: false, isGradingAutoPublished: false, displayInDashboard: false, + isMinigame: false, hasTokenCounter: false, hasVotingFeatures: false, hoursBeforeEarlyXpDecay: 0, diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts index b9c57609b8..22fd478e99 100644 --- a/src/commons/sagas/BackendSaga.ts +++ b/src/commons/sagas/BackendSaga.ts @@ -957,6 +957,7 @@ const newBackendSagaTwo = combineSagaHandlers(sagaActions, { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 0, hasTokenCounter: false, hasVotingFeatures: false, diff --git a/src/commons/sagas/__tests__/BackendSaga.ts b/src/commons/sagas/__tests__/BackendSaga.ts index 3111a21901..e707c49261 100644 --- a/src/commons/sagas/__tests__/BackendSaga.ts +++ b/src/commons/sagas/__tests__/BackendSaga.ts @@ -177,6 +177,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -188,6 +189,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -199,6 +201,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [ isManuallyGraded: false, isGradingAutoPublished: true, displayInDashboard: false, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -210,6 +213,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [ isManuallyGraded: false, isGradingAutoPublished: false, displayInDashboard: false, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: true, @@ -221,6 +225,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [ isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: false, + isMinigame: false, hoursBeforeEarlyXpDecay: 48, hasTokenCounter: false, hasVotingFeatures: false, @@ -1042,6 +1047,7 @@ describe('Test CREATE_COURSE action', () => { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 0, hasTokenCounter: false, hasVotingFeatures: false, diff --git a/src/features/game/scenes/gameManager/GameGlobalAPI.ts b/src/features/game/scenes/gameManager/GameGlobalAPI.ts index ac407fa84f..abd4009fbe 100644 --- a/src/features/game/scenes/gameManager/GameGlobalAPI.ts +++ b/src/features/game/scenes/gameManager/GameGlobalAPI.ts @@ -1,3 +1,5 @@ +import { getAssessmentOverviews } from 'src/commons/sagas/RequestsSaga'; + import { GameAction } from '../../action/GameActionTypes'; import { SoundAsset } from '../../assets/AssetsTypes'; import { getAwardProp } from '../../awards/GameAwardsHelper'; @@ -450,15 +452,23 @@ class GameGlobalAPI { // Assessment // ///////////////////// - public async promptNavigateToAssessment(assessmentId: number) { + public async promptNavigateToAssessment(assessmentId: string) { const response = await promptWithChoices( GameGlobalAPI.getInstance().getGameManager(), `Are you ready for the challenge?`, ['Yes', 'No'] ); if (response === 0) { - window.open(`/courses/${courseId()}/missions/${assessmentId}/0`, 'blank'); - window.focus(); + const assessments = await getAssessmentOverviews( + SourceAcademyGame.getInstance().getAccountInfo() + ); + if (assessments) { + const { id, type } = assessments.filter( + assessment => assessment.number === assessmentId + )[0]; + window.open(`/courses/${courseId()}/${type.toLowerCase()}/${id}/0`, 'blank'); + window.focus(); + } } } diff --git a/src/features/game/state/GameUserStateManager.ts b/src/features/game/state/GameUserStateManager.ts index 77c8a400f4..e394db3c13 100644 --- a/src/features/game/state/GameUserStateManager.ts +++ b/src/features/game/state/GameUserStateManager.ts @@ -55,7 +55,7 @@ export default class GameUserStateManager { (assessments || []) .filter(assessment => assessment.status === 'submitted') .sort((a, b) => (a.closeAt <= b.closeAt ? -1 : 1)) - .map(assessment => assessment.id.toString()) + .map(assessment => assessment.number || assessment.id.toString()) ); } diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx index 18ca059f82..ef091afd65 100644 --- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx +++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx @@ -31,6 +31,7 @@ const defaultAssessmentConfig: AssessmentConfiguration = { isManuallyGraded: true, isGradingAutoPublished: false, displayInDashboard: true, + isMinigame: false, hoursBeforeEarlyXpDecay: 0, hasTokenCounter: false, hasVotingFeatures: false, @@ -131,6 +132,7 @@ const AssessmentConfigPanel: WithImperativeApi< /* eslint-disable react-hooks/exhaustive-deps */ const setDisplayInDashboard = useCallback(valueSetter('displayInDashboard'), []); + const setIsMinigame = useCallback(valueSetter('isMinigame'), []); const setHasTokenCounter = useCallback(valueSetter('hasTokenCounter'), []); const setHasVotingFeatures = useCallback(valueSetter('hasVotingFeatures'), []); const setEarlyXp = useCallback(valueSetter('earlySubmissionXp'), []); @@ -201,6 +203,15 @@ const AssessmentConfigPanel: WithImperativeApi< field: 'displayInDashboard' } }, + { + headerName: 'Is Minigame', + field: 'isMinigame', + cellRenderer: BooleanCell, + cellRendererParams: { + setStateHandler: setIsMinigame, + field: 'isMinigame' + } + }, { headerName: 'Voting Features*', field: 'hasVotingFeatures',