feat: delete submission
This commit is contained in:
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user