Skip to content

Commit 0d9d5dc

Browse files
committed
Fix: Use logical checking to circumvent setTimeout usage
1 parent 17c28bb commit 0d9d5dc

File tree

7 files changed

+34
-49
lines changed

7 files changed

+34
-49
lines changed

src/commons/application/ApplicationTypes.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,9 @@ export const defaultLeaderboard: LeaderboardState = {
353353
userXp: [],
354354
contestScore: [],
355355
contestPopularVote: [],
356-
code: 'Initial code',
357-
contests: []
356+
code: '',
357+
contests: [],
358+
initialRun: {}
358359
};
359360

360361
const getDefaultLanguageConfig = (): SALanguage => {

src/commons/assessment/Assessment.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import NotificationBadge from '../notificationBadge/NotificationBadge';
4040
import { filterNotificationsByAssessment } from '../notificationBadge/NotificationBadgeHelper';
4141
import Constants from '../utils/Constants';
4242
import { beforeNow, getPrettyDate, getPrettyDateAfterHours } from '../utils/DateHelper';
43-
import { useResponsive, useSession } from '../utils/Hooks';
43+
import { useResponsive, useSession, useTypedSelector } from '../utils/Hooks';
4444
import { assessmentTypeLink, convertParamToInt } from '../utils/ParamParseHelper';
4545
import AssessmentNotFound from './AssessmentNotFound';
4646
import {
@@ -272,6 +272,7 @@ const Assessment: React.FC = () => {
272272

273273
const assessmentId: number | null = convertParamToInt(params.assessmentId);
274274
const questionId: number = convertParamToInt(params.questionId) || Constants.defaultQuestionId;
275+
const fromLeaderboard: boolean = useTypedSelector(store => store.leaderboard.code) ? true : false;
275276

276277
// If there is an assessment to render, create a workspace. The assessment
277278
// overviews must still be loaded for this, to send the due date.
@@ -290,7 +291,8 @@ const Assessment: React.FC = () => {
290291
canSave:
291292
role !== Role.Student ||
292293
(overview.status !== AssessmentStatuses.submitted && !beforeNow(overview.closeAt)),
293-
assessmentConfiguration: assessmentConfigToLoad
294+
assessmentConfiguration: assessmentConfigToLoad,
295+
fromContestLeaderboard: fromLeaderboard
294296
};
295297
return <AssessmentWorkspace {...assessmentWorkspaceProps} />;
296298
}

src/commons/assessmentWorkspace/AssessmentWorkspace.tsx

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import classNames from 'classnames';
1515
import { Chapter, Variant } from 'js-slang/dist/types';
1616
import { isEqual } from 'lodash';
1717
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
18-
import { useDispatch, useStore } from 'react-redux';
18+
import { useDispatch } from 'react-redux';
1919
import { useNavigate } from 'react-router';
2020
import { showSimpleConfirmDialog } from 'src/commons/utils/DialogHelper';
2121
import { onClickProgress } from 'src/features/assessments/AssessmentUtils';
@@ -31,7 +31,7 @@ import {
3131
SelectionRange
3232
} from '../../features/sourceRecorder/SourceRecorderTypes';
3333
import SessionActions from '../application/actions/SessionActions';
34-
import { defaultWorkspaceManager, OverallState } from '../application/ApplicationTypes';
34+
import { defaultWorkspaceManager } from '../application/ApplicationTypes';
3535
import {
3636
AssessmentConfiguration,
3737
AutogradingResult,
@@ -86,6 +86,7 @@ export type AssessmentWorkspaceProps = {
8686
notAttempted: boolean;
8787
canSave: boolean;
8888
assessmentConfiguration: AssessmentConfiguration;
89+
fromContestLeaderboard: boolean;
8990
};
9091

9192
const workspaceLocation: WorkspaceLocation = 'assessment';
@@ -187,25 +188,16 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
187188
};
188189
}, [dispatch]);
189190

190-
const code = useTypedSelector(store => store.leaderboard.code) || 'Initial code';
191-
const state = useStore<OverallState>();
192-
useEffect(() => {
193-
console.log('CODE: ', code);
194-
const timeoutId = setTimeout(() => {
195-
if (code !== 'Initial code') {
196-
console.log('UPDATING');
197-
dispatch(WorkspaceActions.updateEditorValue(workspaceLocation, 0, code));
198-
console.log(
199-
'UPDATED EDITOR VALUE WORKSPACE: ',
200-
state.getState().workspaces[workspaceLocation].editorTabs[0].value
201-
);
202-
}
191+
const code = useTypedSelector(store => store.leaderboard.code);
192+
const initialRunCompleted = useTypedSelector(store => store.leaderboard.initialRun);
193+
const votingId = props.assessmentId;
203194

204-
// Clear the code after the delay
195+
useEffect(() => {
196+
if (initialRunCompleted[votingId] && props.fromContestLeaderboard && code != '') {
197+
dispatch(WorkspaceActions.updateEditorValue(workspaceLocation, 0, code));
205198
dispatch(LeaderboardActions.clearCode());
206-
}, 0);
207-
return () => clearTimeout(timeoutId);
208-
}, [dispatch, code]);
199+
}
200+
}, [dispatch]);
209201

210202
useEffect(() => {
211203
if (assessmentOverview && assessmentOverview.maxTeamSize > 1) {
@@ -237,29 +229,6 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
237229
if (!assessment) {
238230
return;
239231
}
240-
// ------------- PLEASE NOTE, EVERYTHING BELOW THIS SEEMS TO BE UNUSED -------------
241-
// checkWorkspaceReset does exactly the same thing.
242-
let questionId = props.questionId;
243-
if (props.questionId >= assessment.questions.length) {
244-
questionId = assessment.questions.length - 1;
245-
}
246-
247-
const question = assessment.questions[questionId];
248-
249-
let answer = '';
250-
if (question.type === QuestionTypes.programming) {
251-
if (question.answer) {
252-
answer = (question as IProgrammingQuestion).answer as string;
253-
} else {
254-
answer = (question as IProgrammingQuestion).solutionTemplate;
255-
}
256-
} else if (question.type === QuestionTypes.voting && code !== 'Initial code') {
257-
answer = code;
258-
}
259-
260-
// TODO: Hardcoded to make use of the first editor tab. Refactoring is needed for this workspace to enable Folder mode.
261-
handleEditorValueChange(0, answer);
262-
// eslint-disable-next-line react-hooks/exhaustive-deps
263232
}, []);
264233

265234
/**
@@ -268,7 +237,10 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
268237
*/
269238
useEffect(() => {
270239
checkWorkspaceReset();
271-
});
240+
if (assessment != undefined && question.type == "voting"){
241+
dispatch(LeaderboardActions.setWorkspaceInitialRun(votingId));
242+
}
243+
}, [dispatch, assessment]);
272244

273245
/**
274246
* Handles toggling enabling and disabling token counter depending on assessment properties
@@ -410,6 +382,7 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
410382
case QuestionTypes.voting:
411383
const votingQuestionData: IContestVotingQuestion = question;
412384
options.programPrependValue = votingQuestionData.prepend;
385+
if (props.fromContestLeaderboard) options.editorValue = code;
413386
options.programPostpendValue = votingQuestionData.postpend;
414387
break;
415388
case QuestionTypes.mcq:

src/commons/sideContent/content/SideContentContestLeaderboard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const SideContentContestLeaderboard: React.FC<SideContentContestLeaderboardProps
8383
key={contestEntry.submission_id}
8484
handleContestEntryClick={handleContestEntryClick}
8585
contestEntry={contestEntry}
86-
rank={contestEntry.rank ?? 1}
86+
rank={contestEntry.rank ?? index + 1}
8787
/>
8888
))
8989
) : (

src/features/leaderboard/LeaderboardActions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ const LeaderboardActions = createActions('leaderboard', {
1414
clearCode: 0,
1515
getContests: 0,
1616
saveContests: (contests: LeaderboardContestDetails[]) => contests,
17+
setWorkspaceInitialRun: (contestID: number) => contestID,
18+
resetWorkspaceInitialRun: (contestID: number) => contestID
1719
});
1820

1921
export default LeaderboardActions;

src/features/leaderboard/LeaderboardReducer.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ export const LeaderboardReducer: Reducer<LeaderboardState, SourceActionType> = c
2626
})
2727
.addCase(LeaderboardActions.saveContests, (state, action) => {
2828
state.contests = action.payload;
29-
});
29+
})
30+
.addCase(LeaderboardActions.setWorkspaceInitialRun, (state, action) => {
31+
state.initialRun[action.payload] = true;
32+
})
33+
.addCase(LeaderboardActions.resetWorkspaceInitialRun, (state, action) => {
34+
state.initialRun[action.payload] = false;
35+
})
3036
}
3137
);

src/features/leaderboard/LeaderboardTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export type LeaderboardState = {
2424
contestPopularVote: ContestLeaderboardRow[];
2525
code: string;
2626
contests: LeaderboardContestDetails[];
27+
initialRun: {[id: number]: boolean};
2728
};
2829

2930
export type LeaderboardContestDetails = {

0 commit comments

Comments
 (0)