feat: delete submission

This commit is contained in:
Rotimi Best
2024-08-03 20:58:07 +01:00
parent e8de6b9457
commit 30a6193e3c
20 changed files with 305 additions and 161 deletions
@@ -15,7 +15,7 @@
import PageBody from '$lib/components/PageBody/index.svelte';
import Box from '$lib/components/Box/index.svelte';
import { course, group } from '$lib/components/Course/store';
import { getLectureNo } from '$lib/components/Course/function';
import { getLectureNo } from '$lib/components/Course/function.js';
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
import { ROLE } from '$lib/utils/constants/roles';
import { takeAttendance } from '$lib/utils/services/attendance';
@@ -117,7 +117,7 @@
function searchStudents(query: string, _students: GroupPerson[]) {
const lowercaseQuery = query.toLowerCase();
return _students.filter((student) =>
student.profile.fullname.toLowerCase().includes(lowercaseQuery)
student.profile?.fullname?.toLowerCase()?.includes(lowercaseQuery)
);
}
@@ -272,7 +272,9 @@
<DateField
value={formatDate(lesson.lesson_at)}
className="p-2 my-2 rounded-md sm:w-[179px] dark:bg-neutral-800 dark:text-white"
onChange={(e) => (lesson.lesson_at = e.target.value)}
onChange={(e) => {
lesson.lesson_at = e?.target?.value;
}}
/>
{:else}
<div class="mb-2 flex">
@@ -19,7 +19,7 @@
import PageBody from '$lib/components/PageBody/index.svelte';
import Materials from '$lib/components/Course/components/Lesson/Materials/index.svelte';
import Exercises from '$lib/components/Course/components/Lesson/Exercises/index.svelte';
import LanguageLessonVersionHistory from '$lib/components/Course/components/Lesson/LanguageLessonVersionHistory.svelte';
import LessonVersionHistory from '$lib/components/Course/components/Lesson/LessonVersionHistory.svelte';
import MODES from '$lib/utils/constants/mode';
import { course } from '$lib/components/Course/store';
import Download from 'carbon-icons-svelte/lib/Download.svelte';
@@ -458,7 +458,7 @@
<!-- Version Control Preview -->
{#if isVersionDrawerOpen && window.innerWidth >= 1024}
<LanguageLessonVersionHistory
<LessonVersionHistory
open={isVersionDrawerOpen}
on:close={() => (isVersionDrawerOpen = false)}
on:restore={refetchDataAfterVersionRestore}
@@ -10,7 +10,7 @@
import { group } from '$lib/components/Course/store';
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
import { fetchExercisesByMarks } from '$lib/utils/services/courses';
import { getLectureNo } from '$lib/components/Course/function';
import { getLectureNo } from '$lib/components/Course/function.js';
import { fetchMarks } from '$lib/utils/services/marks';
import { profile } from '$lib/utils/store/user';
import { browser } from '$app/environment';
@@ -13,9 +13,10 @@
import {
fetchSubmissions,
updateSubmission,
updateQuestionAnswer
} from '$lib/utils/services/submissions/index';
import { formatAnswers } from '$lib/components/Course/function';
updateQuestionAnswer,
deleteSubmission
} from '$lib/utils/services/submissions';
import { formatAnswers } from '$lib/components/Course/function.js';
import { snackbar } from '$lib/components/Snackbar/store';
import isSubmissionEarly from '$lib/utils/functions/isSubmissionEarly';
import formatDate from '$lib/utils/functions/formatDate';
@@ -26,29 +27,11 @@
import { currentOrg, currentOrgDomain } from '$lib/utils/store/org';
import { browser } from '$app/environment';
import { t } from '$lib/utils/functions/translations';
type items = {
id: number;
statusId: number;
isEarly: boolean;
submittedAt: string;
exercise: {
id: string;
title: string;
};
answers: string;
student: any;
lesson: {
id: string | any;
title: string | any;
};
};
type sectionType = {
id: number;
title: string;
value: number;
items: items[] | [];
};
import type {
SubmissionIdData,
SubmissionItem,
SubmissionSection
} from '$lib/utils/types/submission';
export let data;
const { courseId } = data;
@@ -58,8 +41,8 @@
let lessonDetails: { id: string; title: string };
let totalMark = 0;
let maxMark = 0;
let submissionIdData: { [key: number]: any } = {};
let submissionId: string | number | null;
let submissionIdData: { [key: number]: SubmissionIdData } = {};
let submissionId: string;
let openExercise = false;
let isGradeWithAI = false;
@@ -69,7 +52,7 @@
3: $t('course.navItem.submissions.submission_status.graded')
};
let sections: sectionType[] = [
let sections: SubmissionSection[] = [
{
id: 1,
title: $t('course.navItem.submissions.submission_status.submitted'),
@@ -104,16 +87,16 @@
totalMark = calculateTotal(submissionData?.questionAnswerByPoint);
const { fullname, email } = submissionData?.student;
const { title, status_id }: { title: string; status_id: number } = submissionData;
const { title, statusId }: { title: string; statusId: number } = submissionData;
const exerciseLink = `${$currentOrgDomain}/courses/${courseId}/lessons/${lessonDetails.id}/exercises/${exerciseDetails.id}`;
const content = `
<p>Hello ${fullname},</p>
<p>The status of your submitted exercise on <strong>${title}</strong> has been updated to ${
submissionStatus[status_id]
submissionStatus[statusId]
}</p>
${
status_id == 3
statusId == 3
? `<p>Your score was ${totalMark}/${maxMark}</p>
<a class="button" href="${exerciseLink}">View your Result</a>
`
@@ -133,9 +116,9 @@
function handleItemFinalize(
columnIdx: number,
newItems: { map: (arg0: (item: items) => items) => items[] }
newItems: { map: (arg0: (item: SubmissionItem) => SubmissionItem) => SubmissionItem[] }
) {
let itemToWithNewStatus: items | undefined;
let itemToWithNewStatus: SubmissionItem | undefined;
const { id } = sections[columnIdx];
@@ -154,7 +137,7 @@
// Update key mapping for each submission also
submissionIdData[itemToWithNewStatus.id] = {
...submissionIdData[itemToWithNewStatus.id],
status_id: itemToWithNewStatus.statusId
statusId: itemToWithNewStatus.statusId
};
notifyStudent(submissionIdData[itemToWithNewStatus.id]);
@@ -188,12 +171,12 @@
nextStatusId,
total
}: {
submissionId: number;
submissionId: string;
prevStatusId: number;
nextStatusId: number;
total: number;
}) {
let itemToWithNewStatus: items | undefined;
let itemToWithNewStatus: SubmissionItem | undefined;
// Remove from current column
const { items } = sections[prevStatusId - 1];
@@ -218,7 +201,7 @@
// Update key mapping for each submission also
submissionIdData[itemToWithNewStatus.id] = {
...submissionIdData[itemToWithNewStatus.id],
status_id: itemToWithNewStatus.statusId
statusId: itemToWithNewStatus.statusId
};
notifyStudent(submissionIdData[itemToWithNewStatus.id]);
@@ -231,6 +214,28 @@
}
}
async function handleDeleteSubmission(id: string, statusId: number) {
const { items } = sections[statusId - 1];
sections[statusId - 1].items = items?.filter((item) => {
return item.id === id ? false : true;
});
submissionIdData[id] = undefined;
const { error } = await deleteSubmission(id);
if (error) {
console.error('Error deleting submission', error);
snackbar.error('course.navItem.submissions.grading_modal.delete_error');
return;
}
snackbar.success('course.navItem.submissions.grading_modal.delete_success');
handleModalClose();
}
async function handleSave(submission: {
questionAnswerByPoint: any;
questionAnswers: any;
@@ -262,25 +267,19 @@
await Promise.all(updates);
}
$: {
const query = new URLSearchParams($page.url.search);
submissionId = query.get('submissionId');
openExercise = !!submissionId && submissionIdData[submissionId];
}
async function firstRender(courseId: string) {
const { data: submissions } = await fetchSubmissions(courseId);
const sectionById: { [key: number]: sectionType[] } = {};
const sectionById: { [key: number]: SubmissionSection[] } = {};
if (submissions) {
for (const submission of submissions) {
const { id, created_at, exercise, course, answers, groupmember, status_id, feedback } =
submission;
const { id, created_at, answers, groupmember, feedback, exercise } = submission;
const isEarly = isSubmissionEarly(created_at, exercise.due_by);
const submissionItem = {
id,
statusId: status_id,
statusId: submission.status_id,
isEarly,
feedback,
submittedAt: formatDate(created_at),
@@ -295,14 +294,17 @@
title: exercise.lesson.title
}
};
exerciseDetails = { id: submissionItem.exercise.id, title: submissionItem.exercise.title };
lessonDetails = {
id: submissionItem.lesson.id,
title: submissionItem.lesson.title
};
submissionIdData[id] = {
id,
status_id,
statusId: submissionItem.statusId,
feedback,
isEarly,
title: exercise.title,
@@ -317,10 +319,10 @@
}, {})
};
if (Array.isArray(sectionById[status_id])) {
sectionById[status_id].push(submissionItem);
if (Array.isArray(sectionById[submission.status_id])) {
sectionById[submission.status_id].push(submissionItem);
} else {
sectionById[status_id] = [submissionItem];
sectionById[submission.status_id] = [submissionItem];
}
}
}
@@ -333,6 +335,11 @@
}
$: browser && $course.id && firstRender($course.id);
$: {
const query = new URLSearchParams($page.url.search);
submissionId = query.get('submissionId') ?? '';
openExercise = !!submissionId && submissionIdData[submissionId];
}
</script>
<MarkExerciseModal
@@ -341,7 +348,7 @@
data={submissionIdData[submissionId] || {}}
{handleSave}
{updateStatus}
{submissionId}
deleteSubmission={handleDeleteSubmission}
bind:isGradeWithAI
/>
@@ -403,7 +410,6 @@
>
<p class="dark:text-white text-grey text-sm">
#{item.lesson.title}
{`${item.tutor ? 'created by' + item.tutor.name : ''}`}
</p>
</a>
<p class="dark:text-white text-gray-500 text-xs">