From 88a2b6998084b133ce5b637d7633d81d3abe3221 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Fri, 20 Jun 2025 19:59:10 +0530 Subject: [PATCH] feat: exercise form and submission list --- frontend/components.d.ts | 1 + frontend/src/components/AppSidebar.vue | 17 ++ frontend/src/components/AssessmentPlugin.vue | 30 ++- .../src/components/Controls/ChildTable.vue | 140 ++++++++++ frontend/src/components/Controls/Code.vue | 1 - frontend/src/components/MobileLayout.vue | 9 + frontend/src/global.d.ts | 11 + frontend/src/pages/Assignments.vue | 7 +- frontend/src/pages/Courses.vue | 2 +- frontend/src/pages/Lesson.vue | 9 +- frontend/src/pages/LessonForm.vue | 14 +- .../ProgrammingExerciseForm.vue | 206 +++++++++++++++ .../ProgrammingExerciseModal.vue | 4 +- .../ProgrammingExerciseSubmission.vue | 7 +- .../ProgrammingExerciseSubmissions.vue | 249 ++++++++++++++++++ .../ProgrammingExercises.vue | 140 ++++++++++ .../src/pages/ProgrammingExercises/types.ts | 22 ++ frontend/src/router.js | 4 +- frontend/src/utils/assignment.js | 21 +- frontend/src/utils/index.js | 2 + frontend/src/utils/program.ts | 40 ++- frontend/src/utils/quiz.js | 5 +- frontend/tsconfig.json | 3 +- .../lms_programming_exercise.json | 26 +- .../lms_programming_exercise_submission.json | 17 +- .../doctype/lms_test_case/lms_test_case.json | 2 +- 26 files changed, 938 insertions(+), 51 deletions(-) create mode 100644 frontend/src/components/Controls/ChildTable.vue create mode 100644 frontend/src/global.d.ts rename frontend/src/{components/Modals => pages/ProgrammingExercises}/ProgrammingExerciseModal.vue (90%) create mode 100644 frontend/src/pages/ProgrammingExercises/types.ts diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 2e6c67de..a69cab6e 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -32,6 +32,7 @@ declare module 'vue' { Categories: typeof import('./src/components/Settings/Categories.vue')['default'] CertificationLinks: typeof import('./src/components/CertificationLinks.vue')['default'] ChapterModal: typeof import('./src/components/Modals/ChapterModal.vue')['default'] + ChildTable: typeof import('./src/components/Controls/ChildTable.vue')['default'] Code: typeof import('./src/components/Controls/Code.vue')['default'] CodeEditor: typeof import('./src/components/Controls/CodeEditor.vue')['default'] CollapseSidebar: typeof import('./src/components/Icons/CollapseSidebar.vue')['default'] diff --git a/frontend/src/components/AppSidebar.vue b/frontend/src/components/AppSidebar.vue index e2374354..1379bc7f 100644 --- a/frontend/src/components/AppSidebar.vue +++ b/frontend/src/components/AppSidebar.vue @@ -343,6 +343,22 @@ const addAssignments = () => { } } +const addProgrammingExercises = () => { + if (isInstructor.value || isModerator.value) { + sidebarLinks.value.push({ + label: 'Programming Exercises', + icon: 'Code', + to: 'ProgrammingExercises', + activeFor: [ + 'ProgrammingExercises', + 'ProgrammingExerciseForm', + 'ProgrammingExerciseSubmissionList', + 'ProgrammingExerciseSubmission', + ], + }) + } +} + const addPrograms = () => { let activeFor = ['Programs', 'ProgramForm'] let index = 1 @@ -628,6 +644,7 @@ watch(userResource, () => { addPrograms() addQuizzes() addAssignments() + addProgrammingExercises() setUpOnboarding() } }) diff --git a/frontend/src/components/AssessmentPlugin.vue b/frontend/src/components/AssessmentPlugin.vue index 21f8895e..eae9763e 100644 --- a/frontend/src/components/AssessmentPlugin.vue +++ b/frontend/src/components/AssessmentPlugin.vue @@ -2,17 +2,24 @@ - diff --git a/frontend/src/components/Controls/Code.vue b/frontend/src/components/Controls/Code.vue index a14060b8..53aa2091 100644 --- a/frontend/src/components/Controls/Code.vue +++ b/frontend/src/components/Controls/Code.vue @@ -59,7 +59,6 @@ const code = ref('') watch( () => props.modelValue, (newVal) => { - console.log('newVal', newVal) code.value = typeof newVal === 'string' ? newVal : JSON.stringify(newVal, null, 2) }, diff --git a/frontend/src/components/MobileLayout.vue b/frontend/src/components/MobileLayout.vue index 1288c110..ae4c22fd 100644 --- a/frontend/src/components/MobileLayout.vue +++ b/frontend/src/components/MobileLayout.vue @@ -138,6 +138,7 @@ watch(userResource, () => { ) { addQuizzes() addAssignments() + addProgrammingExercises() } }) @@ -157,6 +158,14 @@ const addAssignments = () => { }) } +const addProgrammingExercises = () => { + otherLinks.value.push({ + label: 'Programming Exercises', + icon: 'Code', + to: 'ProgrammingExercises', + }) +} + let isActive = (tab) => { return tab.activeFor?.includes(router.currentRoute.value.name) } diff --git a/frontend/src/global.d.ts b/frontend/src/global.d.ts new file mode 100644 index 00000000..6af9dfe4 --- /dev/null +++ b/frontend/src/global.d.ts @@ -0,0 +1,11 @@ +export {} + +declare global { + function __(text: string): string +} + +declare module 'vue' { + interface ComponentCustomProperties { + __: (text: string) => string + } +} \ No newline at end of file diff --git a/frontend/src/pages/Assignments.vue b/frontend/src/pages/Assignments.vue index bf10174d..a2e00f02 100644 --- a/frontend/src/pages/Assignments.vue +++ b/frontend/src/pages/Assignments.vue @@ -22,14 +22,11 @@
-
+
{{ __('{0} Assignments').format(assignmentCount) }}
{ startTimer() + console.log(sidebarStore.isSidebarCollapsed) + sidebarStore.isSidebarCollapsed = true document.addEventListener('fullscreenchange', attachFullscreenEvent) socket.on('update_lesson_progress', (data) => { if (data.course === props.courseName) { @@ -357,6 +361,7 @@ const attachFullscreenEvent = () => { onBeforeUnmount(() => { document.removeEventListener('fullscreenchange', attachFullscreenEvent) + sidebarStore.isSidebarCollapsed = false }) const lesson = createResource({ @@ -554,7 +559,7 @@ const canGoZen = () => { user.data?.is_instructor || user.data?.is_evaluator ) - return false + return true if (lesson.data?.membership) return true return false } diff --git a/frontend/src/pages/LessonForm.vue b/frontend/src/pages/LessonForm.vue index 2bff40b0..52e89090 100644 --- a/frontend/src/pages/LessonForm.vue +++ b/frontend/src/pages/LessonForm.vue @@ -210,7 +210,7 @@ const addInstructorNotes = (data) => { const enableAutoSave = () => { autoSaveInterval = setInterval(() => { saveLesson({ showSuccessMessage: false }) - }, 5000) + }, 10000) } const keyboardShortcut = (e) => { @@ -385,8 +385,10 @@ const saveLesson = (e) => { showSuccessMessage = true } editor.value.save().then((outputData) => { + outputData = removeEmptyBlocks(outputData) lesson.content = JSON.stringify(outputData) instructorEditor.value.save().then((outputData) => { + outputData = removeEmptyBlocks(outputData) lesson.instructor_content = JSON.stringify(outputData) if (lessonDetails.data?.lesson) { editCurrentLesson() @@ -397,6 +399,14 @@ const saveLesson = (e) => { }) } +const removeEmptyBlocks = (outputData) => { + let blocks = outputData.blocks.filter((block) => { + return Object.keys(block.data).length > 0 || block.type == 'paragraph' + }) + outputData.blocks = blocks + return outputData +} + const createNewLesson = () => { newLessonResource.submit( {}, @@ -686,7 +696,7 @@ iframe { } .ce-popover--opened > .ce-popover__container { - max-height: 320px; + max-height: unset; } .cdx-search-field__icon svg { diff --git a/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue b/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue index e69de29b..25e29514 100644 --- a/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue +++ b/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue @@ -0,0 +1,206 @@ + + diff --git a/frontend/src/components/Modals/ProgrammingExerciseModal.vue b/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue similarity index 90% rename from frontend/src/components/Modals/ProgrammingExerciseModal.vue rename to frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue index fd30be91..8b287008 100644 --- a/frontend/src/components/Modals/ProgrammingExerciseModal.vue +++ b/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseModal.vue @@ -19,8 +19,8 @@
diff --git a/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue b/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue index d3512ea0..2d2bb3f4 100644 --- a/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue +++ b/frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue @@ -1,5 +1,6 @@