From be8566385b52033746c43391351d6ea47c887596 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Mon, 27 Jan 2025 13:25:51 +0800 Subject: [PATCH 01/15] Add Grading comment selector basic UI --- .../subcomponents/GradingCommentSelector.tsx | 26 +++++++++++++++++ .../grading/subcomponents/GradingEditor.tsx | 6 ++++ src/pages/playground/Playground.tsx | 6 +++- src/styles/_workspace.scss | 29 +++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx mode change 100755 => 100644 src/styles/_workspace.scss diff --git a/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx b/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx new file mode 100644 index 0000000000..4abc4a5dae --- /dev/null +++ b/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx @@ -0,0 +1,26 @@ +import React from "react"; + +type Props = { + comments: string[], + setEditor: React.Dispatch> +}; + +const GradingCommentSelector : React.FC = (prop) => { + return ( +
+
+ Comment Suggestions: +
+ {prop.comments.map(el => { + return
{prop.setEditor(el)}} + > + {el} +
+ })} +
+ ) +} + +export default GradingCommentSelector \ No newline at end of file diff --git a/src/pages/academy/grading/subcomponents/GradingEditor.tsx b/src/pages/academy/grading/subcomponents/GradingEditor.tsx index 3c162606dd..e121f28987 100644 --- a/src/pages/academy/grading/subcomponents/GradingEditor.tsx +++ b/src/pages/academy/grading/subcomponents/GradingEditor.tsx @@ -25,6 +25,7 @@ import { showWarningMessage } from '../../../../commons/utils/notifications/NotificationsHelper'; import { convertParamToInt } from '../../../../commons/utils/ParamParseHelper'; +import GradingCommentSelector from './GradingCommentSelector'; type GradingSaveFunction = ( submissionId: number, @@ -303,6 +304,11 @@ const GradingEditor: React.FC = props => { + +
= props => {
) : ( +
- + + + {false && }
); }; diff --git a/src/styles/_workspace.scss b/src/styles/_workspace.scss old mode 100755 new mode 100644 index 63af80872f..7f941dc539 --- a/src/styles/_workspace.scss +++ b/src/styles/_workspace.scss @@ -340,6 +340,35 @@ $code-color-notification: #f9f0d7; } } + .grading-comment-selector { + text-align: center; + display: flex !important; + justify-content: center; + flex-direction: column; + font-size: 0.875rem; + border-radius: 4px; + background-color: $cadet-color-1; + margin-top: 4px; + margin-bottom: 4px; + padding: 8px; + } + + .grading-comment-selector-title { + margin-bottom: 8px; + } + + .grading-comment-selector-item { + margin: 4px; + padding: 4px; + background-color: $cadet-color-2; + border: 1px solid $cadet-color-3; + cursor: pointer; + + &:hover { + background-color: $cadet-color-3; + } + } + .react-mde-parent { margin-bottom: 12px; } From 05b449aefedaf6ce4f733a6b8694c7c1f094b5fd Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Tue, 4 Feb 2025 11:39:20 +0800 Subject: [PATCH 02/15] Connect to backend --- src/commons/sagas/RequestsSaga.ts | 20 +++++++++++++ .../subcomponents/GradingCommentSelector.tsx | 29 ++++++++++--------- .../grading/subcomponents/GradingEditor.tsx | 23 ++++++++++++++- src/pages/playground/Playground.tsx | 5 +--- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/commons/sagas/RequestsSaga.ts b/src/commons/sagas/RequestsSaga.ts index 29f88df173..3ad0378394 100644 --- a/src/commons/sagas/RequestsSaga.ts +++ b/src/commons/sagas/RequestsSaga.ts @@ -1331,6 +1331,26 @@ export const removeAssessmentConfig = async ( return resp; }; +/** + * POST /courses/{courseId}/admin/generate-comments/{submissionId}/{questionId} + */ +export const postGenerateComments = async ( + tokens: Tokens, + submission_id: integer, + question_id: integer +): Promise<{comments:string[]} | null> => { + const resp = await request(`${courseId()}/admin/generate-comments/${submission_id}/${question_id}`, 'POST', { + ...tokens + }); + if (!resp || !resp.ok) { + return null; + } + + return await resp.json(); +}; + + + /** * GET /courses/{courseId}/admin/users */ diff --git a/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx b/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx index 4abc4a5dae..3a1a867cc3 100644 --- a/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx +++ b/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx @@ -6,21 +6,22 @@ type Props = { }; const GradingCommentSelector : React.FC = (prop) => { - return ( -
-
- Comment Suggestions: -
- {prop.comments.map(el => { - return
{prop.setEditor(el)}} - > - {el} + + return ( +
+
+ Comment Suggestions:
- })} -
- ) + {prop.comments.map(el => { + return
{prop.setEditor(el)}} + > + {el} +
+ })} +
+ ) } export default GradingCommentSelector \ No newline at end of file diff --git a/src/pages/academy/grading/subcomponents/GradingEditor.tsx b/src/pages/academy/grading/subcomponents/GradingEditor.tsx index e121f28987..f1d5c14456 100644 --- a/src/pages/academy/grading/subcomponents/GradingEditor.tsx +++ b/src/pages/academy/grading/subcomponents/GradingEditor.tsx @@ -27,6 +27,9 @@ import { import { convertParamToInt } from '../../../../commons/utils/ParamParseHelper'; import GradingCommentSelector from './GradingCommentSelector'; +import { useTokens } from 'src/commons/utils/Hooks'; +import { postGenerateComments } from '../../../../commons/sagas/RequestsSaga'; + type GradingSaveFunction = ( submissionId: number, questionId: number, @@ -52,6 +55,7 @@ const gradingEditorButtonClass = 'grading-editor-button'; const GradingEditor: React.FC = props => { const dispatch = useDispatch(); + const tokens = useTokens(); const { handleGradingSave, handleGradingSaveAndContinue, handleReautogradeAnswer } = useMemo( () => ({ @@ -102,6 +106,15 @@ const GradingEditor: React.FC = props => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.submissionId, props.questionId]); + const getCommentSuggestions = async () => { + const resp = await postGenerateComments( + tokens,props.submissionId,props.questionId + ) + return resp + } + + const [suggestions, setSuggestions] = useState([]) + const makeInitialState = () => { setXpAdjustmentInput(props.xpAdjustment.toString()); setEditorValue(props.comments); @@ -307,8 +320,16 @@ const GradingEditor: React.FC = props => { +
= props => { ) : (
- - - {false && } +
); }; From 780a269f033f39b24bf449b9f27ace694ac29e47 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Tue, 4 Feb 2025 11:40:22 +0800 Subject: [PATCH 03/15] Content changes not found but are showing up as changed --- .husky/pre-push | 0 .tool-versions | 1 + scripts/coverage-fix.sh | 0 scripts/test-coveralls.sh | 0 scripts/test.sh | 0 src/styles/_sourcecast.scss | 0 src/styles/_sourcereel.scss | 0 src/styles/index.scss | 0 8 files changed, 1 insertion(+) mode change 100755 => 100644 .husky/pre-push create mode 100644 .tool-versions mode change 100755 => 100644 scripts/coverage-fix.sh mode change 100755 => 100644 scripts/test-coveralls.sh mode change 100755 => 100644 scripts/test.sh mode change 100755 => 100644 src/styles/_sourcecast.scss mode change 100755 => 100644 src/styles/_sourcereel.scss mode change 100755 => 100644 src/styles/index.scss diff --git a/.husky/pre-push b/.husky/pre-push old mode 100755 new mode 100644 diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000000..1a3e61bfce --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +nodejs v20.18.1 diff --git a/scripts/coverage-fix.sh b/scripts/coverage-fix.sh old mode 100755 new mode 100644 diff --git a/scripts/test-coveralls.sh b/scripts/test-coveralls.sh old mode 100755 new mode 100644 diff --git a/scripts/test.sh b/scripts/test.sh old mode 100755 new mode 100644 diff --git a/src/styles/_sourcecast.scss b/src/styles/_sourcecast.scss old mode 100755 new mode 100644 diff --git a/src/styles/_sourcereel.scss b/src/styles/_sourcereel.scss old mode 100755 new mode 100644 diff --git a/src/styles/index.scss b/src/styles/index.scss old mode 100755 new mode 100644 From 3ae34a09b68d464ef6dc9d55a18551ad832946c7 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Tue, 18 Mar 2025 13:56:11 +0800 Subject: [PATCH 04/15] Hide generate comment button if no LLM prompt --- src/commons/assessment/AssessmentTypes.ts | 2 ++ src/commons/sagas/RequestsSaga.ts | 1 + .../grading/subcomponents/GradingEditor.tsx | 28 +++++++++++-------- .../subcomponents/GradingWorkspace.tsx | 2 ++ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/commons/assessment/AssessmentTypes.ts b/src/commons/assessment/AssessmentTypes.ts index c3d5cecbf4..9cc37f8c52 100644 --- a/src/commons/assessment/AssessmentTypes.ts +++ b/src/commons/assessment/AssessmentTypes.ts @@ -119,6 +119,7 @@ export interface IProgrammingQuestion extends BaseQuestion { prepend: string; postpend: string; solutionTemplate: string; + llm_prompt?: string | null; testcases: Testcase[]; testcasesPrivate?: Testcase[]; // For mission control type: 'programming'; @@ -277,6 +278,7 @@ export const programmingTemplate = (): IProgrammingQuestion => { prepend: '', solutionTemplate: '//This is a mock solution template', postpend: '', + llm_prompt: null, testcases: [], testcasesPrivate: [], type: 'programming', diff --git a/src/commons/sagas/RequestsSaga.ts b/src/commons/sagas/RequestsSaga.ts index 3ad0378394..582c2b2fcf 100644 --- a/src/commons/sagas/RequestsSaga.ts +++ b/src/commons/sagas/RequestsSaga.ts @@ -884,6 +884,7 @@ export const getGrading = async ( solutionTemplate: question.solutionTemplate, prepend: question.prepend || '', postpend: question.postpend || '', + llm_prompt: question.llm_prompt || null, testcases: question.testcases || [], type: question.type as QuestionType, maxXp: question.maxXp diff --git a/src/pages/academy/grading/subcomponents/GradingEditor.tsx b/src/pages/academy/grading/subcomponents/GradingEditor.tsx index f1d5c14456..654ac49b55 100644 --- a/src/pages/academy/grading/subcomponents/GradingEditor.tsx +++ b/src/pages/academy/grading/subcomponents/GradingEditor.tsx @@ -46,6 +46,7 @@ type Props = { maxXp: number; studentNames: string[]; studentUsernames: string[]; + is_llm: boolean; comments: string; graderName?: string; gradedAt?: string; @@ -318,18 +319,21 @@ const GradingEditor: React.FC = props => {
- - + {props.is_llm && +
+ + +
}
= props => { ? [grading!.answers[questionId].student.username] : grading!.answers[questionId].team!.map(member => member.username) } + is_llm={grading!.answers[questionId].question.type == "programming" && + !!grading!.answers[questionId].question.llm_prompt} comments={grading!.answers[questionId].grade.comments ?? ''} graderName={ grading!.answers[questionId].grade.grader From b41843a2f9e0fb773735a0e298d94b54dcc18a70 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Tue, 18 Mar 2025 15:42:17 +0800 Subject: [PATCH 05/15] Input field for API key during Course creation --- src/commons/application/types/SessionTypes.ts | 1 + src/commons/dropdown/DropdownCreateCourse.tsx | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/commons/application/types/SessionTypes.ts b/src/commons/application/types/SessionTypes.ts index 20d4bb4402..feec4a273e 100644 --- a/src/commons/application/types/SessionTypes.ts +++ b/src/commons/application/types/SessionTypes.ts @@ -109,6 +109,7 @@ export type CourseConfiguration = { sourceVariant: Variant; moduleHelpText: string; assetsPrefix: string; + llmAPIKey?: string; }; export type AdminPanelCourseRegistration = { diff --git a/src/commons/dropdown/DropdownCreateCourse.tsx b/src/commons/dropdown/DropdownCreateCourse.tsx index 2d37ce7eb9..c5311fcbbe 100644 --- a/src/commons/dropdown/DropdownCreateCourse.tsx +++ b/src/commons/dropdown/DropdownCreateCourse.tsx @@ -42,7 +42,8 @@ const DropdownCreateCourse: React.FC = props => { enableStories: false, sourceChapter: Chapter.SOURCE_1, sourceVariant: Variant.DEFAULT, - moduleHelpText: '' + moduleHelpText: '', + llmAPIKey: '' }); const [courseHelpTextSelectedTab, setCourseHelpTextSelectedTab] = @@ -273,6 +274,23 @@ const DropdownCreateCourse: React.FC = props => { fill /> + + + setCourseConfig({ + ...courseConfig, + llmAPIKey: e.target.value + }) + } + /> +
+
= props => { }) } /> + + + setCourseConfig({ + ...courseConfig, + enableLlmGrading: (e.target as HTMLInputElement).checked + }) + } + />
From 2d541157bc1d6f3ab17da2b9f76b3d7f70c79289 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Thu, 20 Mar 2025 11:43:47 +0800 Subject: [PATCH 07/15] Disable comment selector if llm grading not enabled --- src/commons/application/types/SessionTypes.ts | 1 + src/pages/academy/grading/subcomponents/GradingWorkspace.tsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commons/application/types/SessionTypes.ts b/src/commons/application/types/SessionTypes.ts index 5dd12eccba..ff60f8660f 100644 --- a/src/commons/application/types/SessionTypes.ts +++ b/src/commons/application/types/SessionTypes.ts @@ -39,6 +39,7 @@ export type SessionState = { readonly enableAchievements?: boolean; readonly enableSourcecast?: boolean; readonly enableStories?: boolean; + readonly enableLlmGrading?: boolean; readonly sourceChapter?: Chapter; readonly sourceVariant?: Variant; readonly moduleHelpText?: string; diff --git a/src/pages/academy/grading/subcomponents/GradingWorkspace.tsx b/src/pages/academy/grading/subcomponents/GradingWorkspace.tsx index e1d5622b9b..d1b1486687 100644 --- a/src/pages/academy/grading/subcomponents/GradingWorkspace.tsx +++ b/src/pages/academy/grading/subcomponents/GradingWorkspace.tsx @@ -62,6 +62,7 @@ const GradingWorkspace: React.FC = props => { const grading = useTypedSelector(state => state.session.gradings[props.submissionId]); const courseId = useTypedSelector(state => state.session.courseId); + const llm_grading = useTypedSelector(state => state.session.enableLlmGrading); const { autogradingResults, isFolderModeEnabled, @@ -304,7 +305,7 @@ const GradingWorkspace: React.FC = props => { ? [grading!.answers[questionId].student.username] : grading!.answers[questionId].team!.map(member => member.username) } - is_llm={grading!.answers[questionId].question.type == "programming" && + is_llm={!!llm_grading && grading!.answers[questionId].question.type == "programming" && !!grading!.answers[questionId].question.llm_prompt} comments={grading!.answers[questionId].grade.comments ?? ''} graderName={ From 928633d857970c77ce89a3c20fd35ffd550f95c6 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Wed, 26 Mar 2025 15:31:57 +0800 Subject: [PATCH 08/15] Added LLM API Key input and integration with backend --- src/commons/application/types/SessionTypes.ts | 2 +- src/commons/dropdown/DropdownCreateCourse.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commons/application/types/SessionTypes.ts b/src/commons/application/types/SessionTypes.ts index ff60f8660f..5498dcda1f 100644 --- a/src/commons/application/types/SessionTypes.ts +++ b/src/commons/application/types/SessionTypes.ts @@ -111,7 +111,7 @@ export type CourseConfiguration = { sourceVariant: Variant; moduleHelpText: string; assetsPrefix: string; - llmAPIKey?: string; + llmApiKey?: string; }; export type AdminPanelCourseRegistration = { diff --git a/src/commons/dropdown/DropdownCreateCourse.tsx b/src/commons/dropdown/DropdownCreateCourse.tsx index c83d222a55..5a3fa6aa73 100644 --- a/src/commons/dropdown/DropdownCreateCourse.tsx +++ b/src/commons/dropdown/DropdownCreateCourse.tsx @@ -44,7 +44,7 @@ const DropdownCreateCourse: React.FC = props => { sourceChapter: Chapter.SOURCE_1, sourceVariant: Variant.DEFAULT, moduleHelpText: '', - llmAPIKey: '' + llmApiKey: '' }); const [courseHelpTextSelectedTab, setCourseHelpTextSelectedTab] = @@ -292,15 +292,15 @@ const DropdownCreateCourse: React.FC = props => { helperText="API Key for LLM comment generation for grading. Will not be enabled if not provided" label={'LLM API Key'} labelInfo="(optional)" - labelFor="llmAPIKey" + labelFor="llmApiKey" > setCourseConfig({ ...courseConfig, - llmAPIKey: e.target.value + llmApiKey: e.target.value }) } /> From 73703b1a6df6ad9855de21a631907bcd89754d06 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Wed, 26 Mar 2025 15:53:28 +0800 Subject: [PATCH 09/15] Add to the course editing panel for llm grading and api key --- src/pages/academy/adminPanel/AdminPanel.tsx | 9 ++++-- .../subcomponents/CourseConfigPanel.tsx | 31 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/pages/academy/adminPanel/AdminPanel.tsx b/src/pages/academy/adminPanel/AdminPanel.tsx index d60edb1647..ee000f96b7 100644 --- a/src/pages/academy/adminPanel/AdminPanel.tsx +++ b/src/pages/academy/adminPanel/AdminPanel.tsx @@ -29,7 +29,9 @@ const defaultCourseConfig: UpdateCourseConfiguration = { enableAchievements: true, enableSourcecast: true, enableStories: false, - moduleHelpText: '' + enableLlmGrading: false, + moduleHelpText: '', + llmApiKey: '' }; const AdminPanel: React.FC = () => { @@ -62,7 +64,9 @@ const AdminPanel: React.FC = () => { enableAchievements: session.enableAchievements, enableSourcecast: session.enableSourcecast, enableStories: session.enableStories, - moduleHelpText: session.moduleHelpText + enableLlmGrading: session.enableLlmGrading, + moduleHelpText: session.moduleHelpText, + llmApiKey: '' }); }, [ session.courseName, @@ -71,6 +75,7 @@ const AdminPanel: React.FC = () => { session.enableGame, session.enableSourcecast, session.enableStories, + session.enableLlmGrading, session.moduleHelpText, session.viewable ]); diff --git a/src/pages/academy/adminPanel/subcomponents/CourseConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/CourseConfigPanel.tsx index 023c659038..61ebad75b3 100644 --- a/src/pages/academy/adminPanel/subcomponents/CourseConfigPanel.tsx +++ b/src/pages/academy/adminPanel/subcomponents/CourseConfigPanel.tsx @@ -38,7 +38,9 @@ const CourseConfigPanel: React.FC = props => { enableAchievements, enableSourcecast, enableStories, - moduleHelpText + enableLlmGrading, + moduleHelpText, + llmApiKey } = props.courseConfiguration; const writePanel = ( @@ -133,6 +135,23 @@ const CourseConfigPanel: React.FC = props => { {courseHelpTextSelectedTab === CourseHelpTextEditorTab.WRITE && writePanel} {courseHelpTextSelectedTab === CourseHelpTextEditorTab.PREVIEW && previewPanel} + + + props.setCourseConfiguration({ + ...props.courseConfiguration, + llmApiKey: e.target.value + }) + } + /> +
{!isMobileBreakpoint && }
@@ -186,6 +205,16 @@ const CourseConfigPanel: React.FC = props => { }) } /> + + props.setCourseConfiguration({ + ...props.courseConfiguration, + enableLlmGrading: (e.target as HTMLInputElement).checked + }) + } + />
From 730cb35786f556733f4889b3a40fbf2ca4488901 Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Sat, 5 Apr 2025 22:17:24 +0800 Subject: [PATCH 10/15] Update localStorage.ts Fix redux state not saving issue --- src/pages/localStorage.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/localStorage.ts b/src/pages/localStorage.ts index 0f9cd6d2d3..583ebb9ed5 100644 --- a/src/pages/localStorage.ts +++ b/src/pages/localStorage.ts @@ -69,6 +69,7 @@ export const saveState = (state: OverallState) => { enableAchievements: state.session.enableAchievements, enableSourcecast: state.session.enableSourcecast, enableStories: state.session.enableStories, + enableLlmGrading: state.session.enableLlmGrading, moduleHelpText: state.session.moduleHelpText, assetsPrefix: state.session.assetsPrefix, assessmentConfigurations: state.session.assessmentConfigurations, From fb4f15d32f5a5d6e31612caaefe1877a9b915cfd Mon Sep 17 00:00:00 2001 From: Eugene Oh Yun Zheng Date: Sun, 6 Apr 2025 15:53:44 +0800 Subject: [PATCH 11/15] Add save chosen and final comment feature Comment selector can now handle selecting multiple suggestions --- src/commons/sagas/RequestsSaga.ts | 26 ++++++++++++++ .../subcomponents/GradingCommentSelector.tsx | 4 +-- .../grading/subcomponents/GradingEditor.tsx | 34 +++++++++++++++++-- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/commons/sagas/RequestsSaga.ts b/src/commons/sagas/RequestsSaga.ts index 582c2b2fcf..b942e393fe 100644 --- a/src/commons/sagas/RequestsSaga.ts +++ b/src/commons/sagas/RequestsSaga.ts @@ -1350,7 +1350,33 @@ export const postGenerateComments = async ( return await resp.json(); }; +export const saveFinalComment = async ( + tokens: Tokens, + submission_id: integer, + question_id: integer, + comment: string +): Promise => { + const resp = await request(`${courseId()}/admin/save-final-comment/${submission_id}/${question_id}`, 'POST', { + body: {"comment": comment}, + ...tokens + }) + + return resp +} +export const saveChosenComments = async ( + tokens: Tokens, + submission_id: integer, + question_id: integer, + comments: string[] +): Promise => { + const resp = await request(`${courseId()}/admin/save-chosen-comments/${submission_id}/${question_id}`, 'POST', { + body: {"comments": comments}, + ...tokens + }) + + return resp +} /** * GET /courses/{courseId}/admin/users diff --git a/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx b/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx index 3a1a867cc3..ddcbe5462c 100644 --- a/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx +++ b/src/pages/academy/grading/subcomponents/GradingCommentSelector.tsx @@ -2,7 +2,7 @@ import React from "react"; type Props = { comments: string[], - setEditor: React.Dispatch> + onSelect: (comment: string) => void }; const GradingCommentSelector : React.FC = (prop) => { @@ -15,7 +15,7 @@ const GradingCommentSelector : React.FC = (prop) => { {prop.comments.map(el => { return
{prop.setEditor(el)}} + onClick={() => {prop.onSelect(el)}} > {el}
diff --git a/src/pages/academy/grading/subcomponents/GradingEditor.tsx b/src/pages/academy/grading/subcomponents/GradingEditor.tsx index 654ac49b55..9a1e53768a 100644 --- a/src/pages/academy/grading/subcomponents/GradingEditor.tsx +++ b/src/pages/academy/grading/subcomponents/GradingEditor.tsx @@ -29,6 +29,8 @@ import GradingCommentSelector from './GradingCommentSelector'; import { useTokens } from 'src/commons/utils/Hooks'; import { postGenerateComments } from '../../../../commons/sagas/RequestsSaga'; +import { saveFinalComment } from '../../../../commons/sagas/RequestsSaga'; +import { saveChosenComments } from '../../../../commons/sagas/RequestsSaga'; type GradingSaveFunction = ( submissionId: number, @@ -109,13 +111,38 @@ const GradingEditor: React.FC = props => { const getCommentSuggestions = async () => { const resp = await postGenerateComments( - tokens,props.submissionId,props.questionId + tokens, props.submissionId, props.questionId ) return resp } + const onSelectGeneratedComments = (comment: string) => { + if (!selectedSuggestions.includes(comment)) { + setSelectedSuggestions([comment, ...selectedSuggestions]) + } + + setEditorValue(editorValue + comment) + } + + const postSaveFinalComment = async (comment : string) => { + const resp = await saveFinalComment( + tokens, props.submissionId, props.questionId, comment + ) + return resp + } + + const postSaveChosenComments = async (comments : string[]) => { + const resp = await saveChosenComments( + tokens, props.submissionId, props.questionId, comments + ) + + return resp + } + const [suggestions, setSuggestions] = useState([]) + const [selectedSuggestions, setSelectedSuggestions] = useState([]) + const makeInitialState = () => { setXpAdjustmentInput(props.xpAdjustment.toString()); setEditorValue(props.comments); @@ -144,6 +171,8 @@ const GradingEditor: React.FC = props => { () => { const newXpAdjustmentInput = convertParamToInt(xpAdjustmentInput || undefined) || undefined; const xp = props.initialXp + (newXpAdjustmentInput || 0); + postSaveFinalComment(editorValue); + postSaveChosenComments(selectedSuggestions); if (xp < 0 || xp > props.maxXp) { showWarningMessage( `XP ${xp.toString()} is out of bounds. Maximum xp is ${props.maxXp.toString()}.` @@ -322,13 +351,12 @@ const GradingEditor: React.FC = props => { {props.is_llm &&
- - {props.is_llm && -
- - -
} + + {props.is_llm && ( +
+ + +
+ )}
= props => { ? [grading!.answers[questionId].student.username] : grading!.answers[questionId].team!.map(member => member.username) } - is_llm={!!llm_grading && grading!.answers[questionId].question.type == "programming"} + is_llm={!!llm_grading && grading!.answers[questionId].question.type == 'programming'} comments={grading!.answers[questionId].grade.comments ?? ''} graderName={ grading!.answers[questionId].grade.grader diff --git a/src/pages/playground/Playground.tsx b/src/pages/playground/Playground.tsx index 01664a13cb..58aeabeebd 100644 --- a/src/pages/playground/Playground.tsx +++ b/src/pages/playground/Playground.tsx @@ -1035,7 +1035,6 @@ const Playground: React.FC = props => {
) : ( -
From b3f5ca7d693ed451e6c992b6537063df5f26e6ce Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Fri, 18 Apr 2025 03:24:20 +0800 Subject: [PATCH 15/15] Revert "Content changes not found but are showing up as changed" This reverts commit 780a269f033f39b24bf449b9f27ace694ac29e47. --- .husky/pre-push | 0 .tool-versions | 1 - scripts/coverage-fix.sh | 0 scripts/test-coveralls.sh | 0 scripts/test.sh | 0 src/styles/_sourcecast.scss | 0 src/styles/_sourcereel.scss | 0 src/styles/index.scss | 0 8 files changed, 1 deletion(-) mode change 100644 => 100755 .husky/pre-push delete mode 100644 .tool-versions mode change 100644 => 100755 scripts/coverage-fix.sh mode change 100644 => 100755 scripts/test-coveralls.sh mode change 100644 => 100755 scripts/test.sh mode change 100644 => 100755 src/styles/_sourcecast.scss mode change 100644 => 100755 src/styles/_sourcereel.scss mode change 100644 => 100755 src/styles/index.scss diff --git a/.husky/pre-push b/.husky/pre-push old mode 100644 new mode 100755 diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index 1a3e61bfce..0000000000 --- a/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -nodejs v20.18.1 diff --git a/scripts/coverage-fix.sh b/scripts/coverage-fix.sh old mode 100644 new mode 100755 diff --git a/scripts/test-coveralls.sh b/scripts/test-coveralls.sh old mode 100644 new mode 100755 diff --git a/scripts/test.sh b/scripts/test.sh old mode 100644 new mode 100755 diff --git a/src/styles/_sourcecast.scss b/src/styles/_sourcecast.scss old mode 100644 new mode 100755 diff --git a/src/styles/_sourcereel.scss b/src/styles/_sourcereel.scss old mode 100644 new mode 100755 diff --git a/src/styles/index.scss b/src/styles/index.scss old mode 100644 new mode 100755