Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
998523d
Implement Versioning and History of Editor Code for Assessment Worksp…
Nocaxe Mar 8, 2026
ef29046
Create tests for versioning and history feature
Nocaxe Mar 9, 2026
fae8626
Prevent submit answer from displaying success message, as submit stat…
Nocaxe Mar 9, 2026
9de2544
Fix updateVersionName API route and getVersionHistory return value
Nocaxe Mar 9, 2026
30b0d51
Fix bug causing double saving, now only submits answer, and allows th…
Nocaxe Mar 9, 2026
de8311a
Change restored versions to be named "(name)-restored" instead of "(t…
Nocaxe Mar 9, 2026
d35c2fe
Prevent autosave in team assessments
Nocaxe Mar 11, 2026
2fc355b
Implement UI for Versioning and History feature
Nocaxe Mar 13, 2026
bd20063
Implement version preview before restoring
Nocaxe Mar 13, 2026
de13c58
Fix bug causing duplicate versions to be saved
Nocaxe Mar 15, 2026
c9367d6
Prevent save status indicator from showing in team assessments
Nocaxe Mar 15, 2026
ed49c48
Update test to not check for success message upon autosave
Nocaxe Mar 15, 2026
0635aae
Update snapshots to align with changes
Nocaxe Mar 15, 2026
bc361e3
Reformatted imports
Nocaxe Mar 15, 2026
13849ea
Fix bug where save status is not correctly checked and updated, alway…
Nocaxe Mar 16, 2026
784c395
Refactor restoreVersionSaga and prevent restoring from auto-submittin…
Nocaxe Mar 16, 2026
f504c5c
Fix bug where renaming updates the timestamp
Nocaxe Mar 16, 2026
cebe414
Fix bug where restoring was renaming the wrong version
Nocaxe Mar 16, 2026
1714803
Merge branch 'master' into Versioning-and-History
martin-henz Mar 16, 2026
78129b8
Merge branch 'master' into Versioning-and-History
Nocaxe Mar 23, 2026
5db4086
Merge branch 'master' into Versioning-and-History
martin-henz Mar 25, 2026
c54384d
update snapshots to match changes
Nocaxe Mar 25, 2026
458b649
Fix bug where new UI is not updated for mobile view
Nocaxe Mar 25, 2026
d8c44cd
Change return type of sagas for better type safety
Nocaxe Mar 25, 2026
a2732b5
Fix bug where restoring will rename an existing version if the code i…
Nocaxe Mar 25, 2026
0c2a634
Memoize sorted array of versions to improve performance
Nocaxe Mar 25, 2026
f253c1a
Fix bug where save button appears incorrectly for individual assessme…
Nocaxe Mar 25, 2026
b9cf3db
Update snapshot to match bug fixes
Nocaxe Mar 25, 2026
4a46a32
Fix formatting
Nocaxe Mar 25, 2026
4b995b6
Fix bug where the restoreVersion action did not take into account the…
Nocaxe Mar 25, 2026
be610df
Fix bug where one auto-save can prematurely unblock another, causing …
Nocaxe Mar 25, 2026
0990d2c
Fix bug where UI would show a stale name if the rename API fails
Nocaxe Mar 25, 2026
9f61970
Change all early returns in performAutoSave to return false instead o…
Nocaxe Mar 25, 2026
1a85f0d
Change onClick prop to match how other control-bar buttons are typed
Nocaxe Mar 25, 2026
9df982f
Fix bug where backend saga mock never updates save status
Nocaxe Mar 25, 2026
2c53280
Change saving status watcher to only work in assessment workspaces
Nocaxe Mar 25, 2026
a5adf24
Fix bug where restoring a version always shows saved even while in th…
Nocaxe Mar 25, 2026
c3023c1
Add check to ensure that timestamp is a naive datetime before appendi…
Nocaxe Mar 25, 2026
1de1ec6
Add safeguard to prevent blanking the editor when restoring a malform…
Nocaxe Mar 25, 2026
5225afb
Edited clickable versions in the panel to be keyboard-focusable and a…
Nocaxe Mar 25, 2026
6deac9f
Add safeguard to prevent slicing the inserted_at when it is null/unde…
Nocaxe Mar 25, 2026
9495078
Fix bug where save button for team assessments is enabled even when a…
Nocaxe Mar 25, 2026
0dcacdf
Merge branch 'master' into Versioning-and-History
RichDom2185 Mar 25, 2026
435ec82
Edit autosaves to only fetch version history if the panel is open to …
Nocaxe Mar 26, 2026
4f4aaed
Remove redundant code
Nocaxe Mar 26, 2026
497a46d
Merge branch 'master' into Versioning-and-History
Nocaxe Mar 26, 2026
231c8a6
Use .reverse() to sort the versions by timestamp instead of .sort() t…
Nocaxe Mar 26, 2026
dcf8bcf
Update field to match backend change
Nocaxe Apr 8, 2026
f8a38fa
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 8, 2026
e5f3b4b
Fix bug where wrong version is renamed after restoring
Nocaxe Apr 8, 2026
5ffbc2f
Add tests for coverage
Nocaxe Apr 8, 2026
683e668
Implement diff viewer when previewing version to restore
Nocaxe Apr 8, 2026
f5491fb
Prevent race condition by making concurrent auto saves wait for the f…
Nocaxe Apr 8, 2026
da5bcbe
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 8, 2026
f454a74
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 12, 2026
25258ca
Fix bug where performAutoSave returns true even if save failed
Nocaxe Apr 12, 2026
5487eb2
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 14, 2026
08d4956
Fix bug where admin panel configuration switches were not animating
Nocaxe Apr 14, 2026
af3a711
Fix bug where hasUnsavedCode is not set to false when restoring ident…
Nocaxe Apr 14, 2026
2d3e6b5
Make code save when history panel is opened
Nocaxe Apr 15, 2026
9d09398
Update tests
Nocaxe Apr 15, 2026
272689f
Implement configuration setting for enabling and disabling autosave p…
Nocaxe Apr 15, 2026
7d711bc
Update tests for configuration of autosave
Nocaxe Apr 15, 2026
2c0379b
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 15, 2026
3b1df73
Update snapshots
Nocaxe Apr 15, 2026
81aff86
Fix bug causing duplicate versions when restoring
Nocaxe Apr 15, 2026
4e95f05
Fix bug causing hasUnsavedChanges to be false even when save failed f…
Nocaxe Apr 15, 2026
dd809ff
Prevent autosaving from fetch and restore when disabled
Nocaxe Apr 15, 2026
08c86da
Update tests
Nocaxe Apr 15, 2026
eb07ea4
Fix bug where autosave was enabled for MCQ
Nocaxe Apr 16, 2026
1dfc2df
Change deduplication check for better performance
Nocaxe Apr 16, 2026
2920ee0
Change restoreVersionSaga to return earlier if autosave is disabled
Nocaxe Apr 16, 2026
c9a7e79
Make auto save return earlier if it is a team assessment
Nocaxe Apr 16, 2026
a285cec
Update tests
Nocaxe Apr 16, 2026
5141592
Improve performance of restoring version by removing redundant search
Nocaxe Apr 17, 2026
496c2ac
Update tests
Nocaxe Apr 17, 2026
96bf596
Improve performance of renaming versions when restoring
Nocaxe Apr 17, 2026
c3e1059
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 17, 2026
441fbad
Change default to enable autosave for assessments created before this…
Nocaxe Apr 17, 2026
03c230c
Implement lazy loading of versions for previewing
Nocaxe Apr 19, 2026
ed44d17
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 19, 2026
01a958d
Implement collapsible grouping of versions in history panel
Nocaxe Apr 19, 2026
03bad56
Remove redundant work following backend changes
Nocaxe Apr 22, 2026
4551dbb
Edit reset confirmation message
Nocaxe Apr 22, 2026
4a96213
Update tests
Nocaxe Apr 22, 2026
efbfc4c
Prevent race condition from hanging and blocking future autosaves
Nocaxe Apr 22, 2026
272c1bf
Change direct calls to fetchVersionHistorySaga to action dispatches i…
Nocaxe Apr 22, 2026
4cdc441
Merge branch 'master' into Versioning-and-History
Nocaxe Apr 22, 2026
bb8dfa9
Prevent possible indefinite hanging of saga
Nocaxe Apr 22, 2026
fdbf228
Add onSelectVersion to the useEffect dependency array
Nocaxe Apr 22, 2026
ef8ef1b
Fix bug where rapid selection of versions can cause incorrect code to…
Nocaxe Apr 22, 2026
69e89c5
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 May 6, 2026
cc11a71
Update lockfile post-merge
RichDom2185 May 6, 2026
93d6d45
Remove duplicate dependency
RichDom2185 May 6, 2026
86dc7d2
Remove unnecessary type assertion
RichDom2185 May 6, 2026
acb334d
Refactor to use SCSS module for scoping
RichDom2185 May 6, 2026
cc57868
Fix global
RichDom2185 May 6, 2026
8302694
Update test snapshots
RichDom2185 May 6, 2026
b238120
Remove unnecessary type assertion
RichDom2185 May 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/commons/application/ApplicationTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,13 @@ export const createDefaultWorkspace = (workspaceLocation: WorkspaceLocation): Wo
debuggerContext: {} as DebuggerContext,
lastDebuggerResult: undefined,
files: {},
updateUserRoleCallback: () => {}
updateUserRoleCallback: () => {},
versionHistory: {
versions: [],
isLoading: false,
isHistoryPanelOpen: false
},
saveStatus: 'idle'
});

const defaultFileName = 'program.js';
Expand Down
76 changes: 59 additions & 17 deletions src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
import { ControlBarResetButton } from '../controlBar/ControlBarResetButton';
import { ControlBarRunButton } from '../controlBar/ControlBarRunButton';
import { ControlButtonSaveButton } from '../controlBar/ControlBarSaveButton';
import { ControlBarSaveStatusIndicator } from '../controlBar/ControlBarSaveStatusIndicator';
import { ControlBarVersionHistoryButton } from '../controlBar/ControlBarVersionHistoryButton';
import { VersionHistoryPanel } from '../controlBar/VersionHistoryPanel';
import ControlButton from '../ControlButton';
import {
convertEditorTabStateToProps,
Expand Down Expand Up @@ -127,7 +130,9 @@
output,
replValue,
currentAssessment: storedAssessmentId,
currentQuestion: storedQuestionId
currentQuestion: storedQuestionId,
versionHistory,
saveStatus
} = useTypedSelector(store => store.workspaces[workspaceLocation]);

const dispatch = useDispatch();
Expand All @@ -148,7 +153,11 @@
handleCheckLastModifiedAt,
handleUpdateHasUnsavedChanges,
handleEnableTokenCounter,
handleDisableTokenCounter
handleDisableTokenCounter,
handleFetchVersionHistory,
handleToggleHistoryPanel,
handleRestoreVersion,
handleNameVersion
} = useMemo(() => {
return {
handleTeamOverviewFetch: (assessmentId: number) =>
Expand Down Expand Up @@ -185,7 +194,15 @@
handleEnableTokenCounter: () =>
dispatch(WorkspaceActions.enableTokenCounter(workspaceLocation)),
handleDisableTokenCounter: () =>
dispatch(WorkspaceActions.disableTokenCounter(workspaceLocation))
dispatch(WorkspaceActions.disableTokenCounter(workspaceLocation)),
handleFetchVersionHistory: () =>
dispatch(WorkspaceActions.fetchVersionHistory(workspaceLocation)),
handleToggleHistoryPanel: () =>
dispatch(WorkspaceActions.toggleHistoryPanel(workspaceLocation)),
handleRestoreVersion: (versionId: string) =>
dispatch(WorkspaceActions.restoreVersion(workspaceLocation, versionId)),
handleNameVersion: (versionId: string, name: string) =>
dispatch(WorkspaceActions.nameVersion(workspaceLocation, versionId, name))
};
}, [dispatch]);

Expand All @@ -198,7 +215,7 @@
dispatch(WorkspaceActions.updateEditorValue(workspaceLocation, 0, code));
dispatch(LeaderboardActions.clearCode());
}
}, [dispatch]);

Check warning on line 218 in src/commons/assessmentWorkspace/AssessmentWorkspace.tsx

View workflow job for this annotation

GitHub Actions / lint (eslint)

React Hook useEffect has missing dependencies: 'code', 'initialRunCompleted', 'props.fromContestLeaderboard', and 'votingId'. Either include them or remove the dependency array

useEffect(() => {
if (assessmentOverview && assessmentOverview.maxTeamSize > 1) {
Expand Down Expand Up @@ -410,6 +427,7 @@
);
handleClearContext(question.library, true);
handleUpdateHasUnsavedChanges(false);
handleFetchVersionHistory();

const chapter = question.library.chapter;
const questionType = question.type;
Expand Down Expand Up @@ -778,25 +796,34 @@
/>
);

// Define the function to check if the Save button should be disabled
const shouldDisableSaveButton = (): boolean | undefined => {
const isIndividualAssessment: boolean = assessmentOverview?.maxTeamSize === 1;
if (isIndividualAssessment) {
return false;
}
return !teamFormationOverview;
};
const isTeamAssessment: boolean = assessmentOverview?.maxTeamSize !== 1;
Comment thread
Nocaxe marked this conversation as resolved.
Outdated

const saveButton =
props.canSave && question.type === QuestionTypes.programming ? (
isTeamAssessment && question.type === QuestionTypes.programming ? (
<ControlButtonSaveButton
key="save"
hasUnsavedChanges={hasUnsavedChanges}
isDisabled={shouldDisableSaveButton()}
onClickSave={onClickSave}
key="save"
isDisabled={!props.canSave}
/>
Comment thread
Nocaxe marked this conversation as resolved.
Outdated
) : null;

const versionHistoryButton =
question.type !== QuestionTypes.mcq ? (
<ControlBarVersionHistoryButton
onClick={() => {
handleFetchVersionHistory();
handleToggleHistoryPanel();
}}
key="version_history"
/>
) : null;

const saveStatusIndicator =
question.type !== QuestionTypes.mcq && !isTeamAssessment ? (
<ControlBarSaveStatusIndicator saveStatus={saveStatus} key="save_status" />
) : null;

const chapterSelect = (
<ControlBarChapterSelect
handleChapterSelect={() => {}}
Expand All @@ -811,8 +838,15 @@
return {
editorButtons:
!isMobileBreakpoint || isVscode
? [runButton, saveButton, resetButton, chapterSelect]
: [saveButton, resetButton],
? [
runButton,
saveButton,
resetButton,
versionHistoryButton,
saveStatusIndicator,
chapterSelect
]
: [resetButton],
Comment thread
Nocaxe marked this conversation as resolved.
Outdated
flowButtons: [previousButton, questionView, nextButton]
};
};
Expand Down Expand Up @@ -943,7 +977,7 @@
>
<DialogBody>
<Markdown content="Are you sure you want to reset the template?" />
<Markdown content="*Note this will not affect the saved copy of your program, unless you save over it.*" />
<Markdown content="*Note this will not affect your version history.*" />
</DialogBody>
<DialogFooter
actions={
Expand Down Expand Up @@ -1050,6 +1084,14 @@
{submissionOverlay}
{overlay}
{resetTemplateOverlay}
<VersionHistoryPanel
versions={versionHistory.versions}
isOpen={versionHistory.isHistoryPanelOpen}
isLoading={versionHistory.isLoading}
onClose={handleToggleHistoryPanel}
onRestore={handleRestoreVersion}
onRename={handleNameVersion}
/>
{isVscode || !isMobileBreakpoint ? (
<Workspace {...workspaceProps} />
) : (
Expand Down
Loading
Loading