feat: delete submission
This commit is contained in:
+4
-4
@@ -18,24 +18,24 @@
|
|||||||
onClose={() => (openDeleteModal = false)}
|
onClose={() => (openDeleteModal = false)}
|
||||||
bind:open={openDeleteModal}
|
bind:open={openDeleteModal}
|
||||||
width="w-96"
|
width="w-96"
|
||||||
modalHeading={$t('course.navItem.lessons.delete_lesson.modal_heading')}
|
modalHeading={$t('delete_modal.label')}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<h1 class="dark:text-white text-lg">
|
<h1 class="dark:text-white text-lg">
|
||||||
{$t('course.navItem.lessons.delete_lesson.content')} <strong>{lessonTitle}</strong>?
|
{$t('delete_modal.content')} <strong>{lessonTitle}</strong>?
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="mt-5 flex items-center justify-between">
|
<div class="mt-5 flex items-center justify-between">
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
className="px-6 py-3"
|
className="px-6 py-3"
|
||||||
variant={VARIANTS.OUTLINED}
|
variant={VARIANTS.OUTLINED}
|
||||||
label={$t('course.navItem.lessons.delete_lesson.no')}
|
label={$t('delete_modal.no')}
|
||||||
onClick={() => (openDeleteModal = false)}
|
onClick={() => (openDeleteModal = false)}
|
||||||
/>
|
/>
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
className="px-6 py-3"
|
className="px-6 py-3"
|
||||||
variant={VARIANTS.OUTLINED}
|
variant={VARIANTS.OUTLINED}
|
||||||
label={$t('course.navItem.lessons.delete_lesson.yes')}
|
label={$t('delete_modal.yes')}
|
||||||
onClick={handleDelete}
|
onClick={handleDelete}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+91
-34
@@ -10,14 +10,21 @@
|
|||||||
import { useCompletion } from 'ai/svelte';
|
import { useCompletion } from 'ai/svelte';
|
||||||
import { QUESTION_TYPE } from '$lib/components/Question/constants';
|
import { QUESTION_TYPE } from '$lib/components/Question/constants';
|
||||||
import { t } from '$lib/utils/functions/translations';
|
import { t } from '$lib/utils/functions/translations';
|
||||||
|
import { OverflowMenu, OverflowMenuItem } from 'carbon-components-svelte';
|
||||||
|
import type { SubmissionIdData } from '$lib/utils/types/submission';
|
||||||
|
|
||||||
export let open = false;
|
export let open = false;
|
||||||
export let onClose = () => {};
|
export let onClose = () => {};
|
||||||
export let handleSave = () => {};
|
export let handleSave = (d: SubmissionIdData) => {};
|
||||||
export let isGradeWithAI = false;
|
export let isGradeWithAI = false;
|
||||||
|
export let data: SubmissionIdData;
|
||||||
export let data = {};
|
export let deleteSubmission = async (id: string, statusId: number) => {};
|
||||||
export let updateStatus = () => {};
|
export let updateStatus = (arg: {
|
||||||
|
submissionId: string;
|
||||||
|
prevStatusId: number;
|
||||||
|
nextStatusId: number;
|
||||||
|
total: number;
|
||||||
|
}) => {};
|
||||||
|
|
||||||
const SELECTABLE_STATUS = [
|
const SELECTABLE_STATUS = [
|
||||||
{
|
{
|
||||||
@@ -40,6 +47,9 @@
|
|||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
let total = 0;
|
let total = 0;
|
||||||
let maxPoints = 0;
|
let maxPoints = 0;
|
||||||
|
let openMenu = false;
|
||||||
|
let openDeletePrompt = false;
|
||||||
|
let isDeleting = false;
|
||||||
|
|
||||||
function getMaxPoints(questions) {
|
function getMaxPoints(questions) {
|
||||||
return (questions || []).reduce((acc, question) => acc + question.points, 0);
|
return (questions || []).reduce((acc, question) => acc + question.points, 0);
|
||||||
@@ -54,12 +64,13 @@
|
|||||||
const newSelectedId = event.detail.selectedId;
|
const newSelectedId = event.detail.selectedId;
|
||||||
|
|
||||||
setStatus({
|
setStatus({
|
||||||
status_id: newSelectedId
|
...data,
|
||||||
|
statusId: newSelectedId
|
||||||
});
|
});
|
||||||
|
|
||||||
updateStatus({
|
updateStatus({
|
||||||
submissionId: data.id,
|
submissionId: data.id,
|
||||||
prevStatusId: data.status_id,
|
prevStatusId: data.statusId,
|
||||||
nextStatusId: status.id,
|
nextStatusId: status.id,
|
||||||
total
|
total
|
||||||
});
|
});
|
||||||
@@ -67,8 +78,8 @@
|
|||||||
snackbar.success(`${$t('snackbar.exercise.submission_updated')} '${status.text}'`);
|
snackbar.success(`${$t('snackbar.exercise.submission_updated')} '${status.text}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setStatus(data) {
|
function setStatus(data: SubmissionIdData) {
|
||||||
const statusBySelectedId = SELECTABLE_STATUS.find((status) => status.id === data.status_id);
|
const statusBySelectedId = SELECTABLE_STATUS.find((status) => status.id === data.statusId);
|
||||||
|
|
||||||
if (!statusBySelectedId) {
|
if (!statusBySelectedId) {
|
||||||
return;
|
return;
|
||||||
@@ -76,18 +87,28 @@
|
|||||||
|
|
||||||
status = statusBySelectedId;
|
status = statusBySelectedId;
|
||||||
|
|
||||||
if (data.status_id !== selectedId) {
|
if (data.statusId !== selectedId) {
|
||||||
selectedId = data.status_id;
|
selectedId = data.statusId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleDeleteSubmission() {
|
||||||
|
isDeleting = true;
|
||||||
|
await deleteSubmission(data.id, status.id);
|
||||||
|
isDeleting = false;
|
||||||
|
}
|
||||||
|
|
||||||
const { input, handleSubmit, completion } = useCompletion({
|
const { input, handleSubmit, completion } = useCompletion({
|
||||||
api: '/api/completion/gradingprompt',
|
api: '/api/completion/gradingprompt',
|
||||||
onFinish: async () => {
|
onFinish: async () => {
|
||||||
try {
|
try {
|
||||||
const responseData = $completion.replace('```json', '').replace('```', '');
|
const responseData = $completion.replace('```json', '').replace('```', '');
|
||||||
|
|
||||||
let aiResponses = [];
|
let aiResponses: {
|
||||||
|
id: number;
|
||||||
|
score: number;
|
||||||
|
explanation: string;
|
||||||
|
}[] = [];
|
||||||
try {
|
try {
|
||||||
// Parse the modified response data as JSON
|
// Parse the modified response data as JSON
|
||||||
aiResponses = JSON.parse(responseData);
|
aiResponses = JSON.parse(responseData);
|
||||||
@@ -100,14 +121,14 @@
|
|||||||
|
|
||||||
if (question_type_id !== QUESTION_TYPE.TEXTAREA) {
|
if (question_type_id !== QUESTION_TYPE.TEXTAREA) {
|
||||||
const answer = data.questionAnswers.find((q) => q.question_id === id);
|
const answer = data.questionAnswers.find((q) => q.question_id === id);
|
||||||
|
const answerPoints = answer?.answers?.length ?? 0;
|
||||||
reasons = {
|
reasons = {
|
||||||
...reasons,
|
...reasons,
|
||||||
[id]: `${$t('course.navItem.submissions.grading_modal.questions_tried')} ${
|
[id]: `${$t(
|
||||||
answer.answers.length
|
'course.navItem.submissions.grading_modal.questions_tried'
|
||||||
} `
|
)} ${answerPoints} `
|
||||||
};
|
};
|
||||||
data.questionAnswerByPoint[id] = points / answer.answers.length;
|
data.questionAnswerByPoint[id] = `${points / answerPoints}`;
|
||||||
} else if (aiResponses.length) {
|
} else if (aiResponses.length) {
|
||||||
const graded = aiResponses.find((res) => res.id === id);
|
const graded = aiResponses.find((res) => res.id === id);
|
||||||
|
|
||||||
@@ -116,7 +137,7 @@
|
|||||||
[id]: `${graded?.explanation}`
|
[id]: `${graded?.explanation}`
|
||||||
};
|
};
|
||||||
|
|
||||||
data.questionAnswerByPoint[id] = graded.score;
|
data.questionAnswerByPoint[id] = `${graded?.score}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -160,26 +181,51 @@
|
|||||||
headerClass="py-2"
|
headerClass="py-2"
|
||||||
labelClass="text-base font-semibold"
|
labelClass="text-base font-semibold"
|
||||||
>
|
>
|
||||||
<div class="w-full h-full">
|
<div class="w-full h-full mt-2">
|
||||||
<Preview
|
{#if openDeletePrompt}
|
||||||
questions={Array.isArray(data.questions)
|
<div class="w-96 mx-auto p-3 border border-gray-300 rounded-md">
|
||||||
? data.questions.sort((a, b) => a.order - b.order)
|
<h1 class="dark:text-white text-lg">
|
||||||
: []}
|
{$t('delete_modal.content')}
|
||||||
questionnaireMetaData={{
|
</h1>
|
||||||
answers: data.answers || {},
|
|
||||||
isFinished: true
|
<div class="mt-5 flex items-center justify-between">
|
||||||
}}
|
<PrimaryButton
|
||||||
bind:grades={data.questionAnswerByPoint}
|
className="px-6 py-3"
|
||||||
bind:reasons
|
variant={VARIANTS.OUTLINED}
|
||||||
bind:isGradeWithAI
|
label={$t('delete_modal.no')}
|
||||||
bind:isLoading
|
onClick={() => (openDeletePrompt = false)}
|
||||||
disableGrading={false}
|
isDisabled={isDeleting}
|
||||||
/>
|
/>
|
||||||
|
<PrimaryButton
|
||||||
|
className="px-6 py-3"
|
||||||
|
variant={VARIANTS.OUTLINED}
|
||||||
|
label={$t('delete_modal.yes')}
|
||||||
|
onClick={handleDeleteSubmission}
|
||||||
|
isLoading={isDeleting}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<Preview
|
||||||
|
questions={Array.isArray(data.questions)
|
||||||
|
? data.questions.sort((a, b) => a.order - b.order)
|
||||||
|
: []}
|
||||||
|
questionnaireMetaData={{
|
||||||
|
answers: data.answers || {},
|
||||||
|
isFinished: true
|
||||||
|
}}
|
||||||
|
bind:grades={data.questionAnswerByPoint}
|
||||||
|
bind:reasons
|
||||||
|
bind:isGradeWithAI
|
||||||
|
bind:isLoading
|
||||||
|
disableGrading={false}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 w-2/5 sticky top-0">
|
<div class="ml-4 mt-2 w-2/5 sticky top-0">
|
||||||
<div class="border border-gray-300 rounded-md">
|
<div class="border border-gray-300 rounded-md">
|
||||||
<div
|
<div
|
||||||
class="hover:bg-gray-100 dark:bg-neutral-800 border-b border-t-0 border-l-0 border-r-0 border-gray-300 p-3"
|
class="flex gap-1 justify-between items-center border-b border-t-0 border-l-0 border-r-0 border-gray-300 p-3"
|
||||||
>
|
>
|
||||||
<p class="dark:text-white font-bold text-base">
|
<p class="dark:text-white font-bold text-base">
|
||||||
{$t('course.navItem.submissions.grading_modal.details')}
|
{$t('course.navItem.submissions.grading_modal.details')}
|
||||||
@@ -193,6 +239,17 @@
|
|||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<OverflowMenu open={openMenu} flipped>
|
||||||
|
<OverflowMenuItem
|
||||||
|
text={$t('delete_modal.label')}
|
||||||
|
on:click={() => {
|
||||||
|
openDeletePrompt = true;
|
||||||
|
openMenu = false;
|
||||||
|
}}
|
||||||
|
danger
|
||||||
|
/>
|
||||||
|
</OverflowMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center space-x-4 text-sm px-3 py-2">
|
<div class="flex items-center space-x-4 text-sm px-3 py-2">
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ export function getLectureNo(index, initNo = '0') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function formatAnswers(data) {
|
export function formatAnswers(data) {
|
||||||
const answers = {};
|
const answers: Record<string, string> = {};
|
||||||
const questionByIdAndName = {};
|
const questionByIdAndName = {};
|
||||||
|
|
||||||
for (const question of data.questions) {
|
for (const question of data.questions) {
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
export let label = '';
|
export let label = '';
|
||||||
export let placeholder = '';
|
export let placeholder = '';
|
||||||
export let value = '';
|
export let value = '';
|
||||||
export let className = '';
|
export let className = '';
|
||||||
export let onChange = () => {}; // This is to know if element is 'dirty'
|
export let onChange = (e?: Event) => {}; // This is to know if element is 'dirty'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label class="block {className}">
|
<label class="block {className}">
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { PostgrestSingleResponse } from '@supabase/supabase-js';
|
|
||||||
import { supabase } from '$lib/utils/functions/supabase';
|
import { supabase } from '$lib/utils/functions/supabase';
|
||||||
import type { ExerciseSubmissions } from '$lib/utils/types';
|
import type { ExerciseSubmissions } from '$lib/utils/types';
|
||||||
|
|
||||||
@@ -87,8 +86,8 @@ export async function updateSubmission(
|
|||||||
status_id,
|
status_id,
|
||||||
total,
|
total,
|
||||||
feedback
|
feedback
|
||||||
}: { id?: number; status_id?: number; total?: number; feedback?: string },
|
}: { id: string; status_id?: number; total?: number; feedback?: string },
|
||||||
otherArgs?: any
|
otherArgs?: Record<string, string>
|
||||||
) {
|
) {
|
||||||
const toUpdate: {
|
const toUpdate: {
|
||||||
status_id?: number;
|
status_id?: number;
|
||||||
@@ -106,6 +105,13 @@ export async function updateSubmission(
|
|||||||
return supabase.from('submission').update(toUpdate, otherArgs).match({ id });
|
return supabase.from('submission').update(toUpdate, otherArgs).match({ id });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateQuestionAnswer(update: any, match: any) {
|
export async function deleteSubmission(id: string) {
|
||||||
|
return supabase.from('submission').delete().match({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateQuestionAnswer(
|
||||||
|
update: Record<string, string>,
|
||||||
|
match: Record<string, string>
|
||||||
|
) {
|
||||||
return supabase.from('question_answer').update(update).match(match);
|
return supabase.from('question_answer').update(update).match(match);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -497,7 +497,10 @@
|
|||||||
"accept_grade": "Akzeptieren",
|
"accept_grade": "Akzeptieren",
|
||||||
"reject_grade": "Ablehnen",
|
"reject_grade": "Ablehnen",
|
||||||
"add_comment_placeholder": "Hinterlasse einen Kommentar",
|
"add_comment_placeholder": "Hinterlasse einen Kommentar",
|
||||||
"questions_tried": "Diese Punktzahl wurde aufgrund der Gesamtzahl der Versuche vergeben:"
|
"questions_tried": "Diese Punktzahl wurde aufgrund der Gesamtzahl der Versuche vergeben:",
|
||||||
|
"delete_prompt": "Löschen",
|
||||||
|
"delete_error": "Die Übermittlung konnte nicht gelöscht werden",
|
||||||
|
"delete_success": "Einreichung erfolgreich gelöscht"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attendance": {
|
"attendance": {
|
||||||
@@ -735,12 +738,6 @@
|
|||||||
"materials": "Materialien",
|
"materials": "Materialien",
|
||||||
"exercises": "Übungen"
|
"exercises": "Übungen"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "Löschen",
|
|
||||||
"content": "Sind Sie sicher, dass Sie löschen möchten:",
|
|
||||||
"no": "NEIN",
|
|
||||||
"yes": "Ja"
|
|
||||||
},
|
|
||||||
"add_lesson": {
|
"add_lesson": {
|
||||||
"button_title": "Hinzufügen",
|
"button_title": "Hinzufügen",
|
||||||
"modal_heading": "Neue Lektion hinzufügen",
|
"modal_heading": "Neue Lektion hinzufügen",
|
||||||
@@ -1390,5 +1387,11 @@
|
|||||||
"empty_heading": "Kein Kurs verfügbar",
|
"empty_heading": "Kein Kurs verfügbar",
|
||||||
"empty_description": "Derzeit sind keine veröffentlichten Kurse verfügbar",
|
"empty_description": "Derzeit sind keine veröffentlichten Kurse verfügbar",
|
||||||
"heading": "Entdecken Sie unsere Kurse"
|
"heading": "Entdecken Sie unsere Kurse"
|
||||||
|
},
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "Löschen",
|
||||||
|
"content": "Bist du sicher?",
|
||||||
|
"no": "NEIN",
|
||||||
|
"yes": "Ja"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,13 @@
|
|||||||
"snackbar_error": "error while sending code"
|
"snackbar_error": "error while sending code"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "Delete",
|
||||||
|
"content": "Are you sure?",
|
||||||
|
"no": "No",
|
||||||
|
"yes": "Yes"
|
||||||
|
},
|
||||||
|
|
||||||
"onboarding": {
|
"onboarding": {
|
||||||
"sell": "Sell courses online",
|
"sell": "Sell courses online",
|
||||||
"teach": "Teach my current students online",
|
"teach": "Teach my current students online",
|
||||||
@@ -514,12 +521,6 @@
|
|||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"delete": "Delete"
|
"delete": "Delete"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "Delete",
|
|
||||||
"content": "Are you sure you want to delete:",
|
|
||||||
"no": "No",
|
|
||||||
"yes": "Yes"
|
|
||||||
},
|
|
||||||
"join_lesson": "Join lesson",
|
"join_lesson": "Join lesson",
|
||||||
"no_link": "No link",
|
"no_link": "No link",
|
||||||
"no_tutor": "No tutor added",
|
"no_tutor": "No tutor added",
|
||||||
@@ -789,7 +790,10 @@
|
|||||||
"submit_grades": "Submit Grades",
|
"submit_grades": "Submit Grades",
|
||||||
"accept_grade": "Accept",
|
"accept_grade": "Accept",
|
||||||
"reject_grade": "Reject",
|
"reject_grade": "Reject",
|
||||||
"questions_tried": "Allocated this score because of total tries:"
|
"questions_tried": "Allocated this score because of total tries:",
|
||||||
|
"delete_prompt": "Delete",
|
||||||
|
"delete_error": "Failed to delete submission",
|
||||||
|
"delete_success": "Successfully deleted submission"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -497,7 +497,10 @@
|
|||||||
"accept_grade": "Aceptar",
|
"accept_grade": "Aceptar",
|
||||||
"reject_grade": "Rechazar",
|
"reject_grade": "Rechazar",
|
||||||
"add_comment_placeholder": "Deja un comentario",
|
"add_comment_placeholder": "Deja un comentario",
|
||||||
"questions_tried": "Se asignó esta puntuación debido al total de intentos:"
|
"questions_tried": "Se asignó esta puntuación debido al total de intentos:",
|
||||||
|
"delete_prompt": "Borrar",
|
||||||
|
"delete_error": "No se pudo eliminar el envío",
|
||||||
|
"delete_success": "Envío eliminado correctamente"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attendance": {
|
"attendance": {
|
||||||
@@ -735,12 +738,6 @@
|
|||||||
"materials": "Materiales",
|
"materials": "Materiales",
|
||||||
"exercises": "Ejercicios"
|
"exercises": "Ejercicios"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "Borrar",
|
|
||||||
"content": "Estas seguro que quieres borrarlo:",
|
|
||||||
"no": "No",
|
|
||||||
"yes": "Sí"
|
|
||||||
},
|
|
||||||
"add_lesson": {
|
"add_lesson": {
|
||||||
"button_title": "Agregar",
|
"button_title": "Agregar",
|
||||||
"modal_heading": "Agregar nueva lección",
|
"modal_heading": "Agregar nueva lección",
|
||||||
@@ -1390,5 +1387,11 @@
|
|||||||
"empty_heading": "No hay curso disponible",
|
"empty_heading": "No hay curso disponible",
|
||||||
"empty_description": "Actualmente no hay ningún curso publicado disponible",
|
"empty_description": "Actualmente no hay ningún curso publicado disponible",
|
||||||
"heading": "Explora nuestros cursos"
|
"heading": "Explora nuestros cursos"
|
||||||
|
},
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "Borrar",
|
||||||
|
"content": "¿Está seguro?",
|
||||||
|
"no": "No",
|
||||||
|
"yes": "Sí"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,10 @@
|
|||||||
"accept_grade": "Accepter",
|
"accept_grade": "Accepter",
|
||||||
"reject_grade": "Rejeter",
|
"reject_grade": "Rejeter",
|
||||||
"add_comment_placeholder": "laissez un commentaire",
|
"add_comment_placeholder": "laissez un commentaire",
|
||||||
"questions_tried": "Attribué ce score en raison du nombre total d'essais :"
|
"questions_tried": "Attribué ce score en raison du nombre total d'essais :",
|
||||||
|
"delete_prompt": "Supprimer",
|
||||||
|
"delete_error": "Échec de la suppression de la soumission",
|
||||||
|
"delete_success": "Soumission supprimée avec succès"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attendance": {
|
"attendance": {
|
||||||
@@ -735,12 +738,6 @@
|
|||||||
"materials": "Matériaux",
|
"materials": "Matériaux",
|
||||||
"exercises": "Des exercices"
|
"exercises": "Des exercices"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "Supprimer",
|
|
||||||
"content": "Etes-vous sûr que vous voulez supprimer:",
|
|
||||||
"no": "Non",
|
|
||||||
"yes": "Oui"
|
|
||||||
},
|
|
||||||
"add_lesson": {
|
"add_lesson": {
|
||||||
"button_title": "Ajouter",
|
"button_title": "Ajouter",
|
||||||
"modal_heading": "Ajouter une nouvelle leçon",
|
"modal_heading": "Ajouter une nouvelle leçon",
|
||||||
@@ -1390,5 +1387,11 @@
|
|||||||
"empty_heading": "Aucun cours disponible",
|
"empty_heading": "Aucun cours disponible",
|
||||||
"empty_description": "Il n'y a actuellement aucun cours publié disponible",
|
"empty_description": "Il n'y a actuellement aucun cours publié disponible",
|
||||||
"heading": "Découvrez nos cours"
|
"heading": "Découvrez nos cours"
|
||||||
|
},
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "Supprimer",
|
||||||
|
"content": "Es-tu sûr?",
|
||||||
|
"no": "Non",
|
||||||
|
"yes": "Oui"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,10 @@
|
|||||||
"accept_grade": "स्वीकार करना",
|
"accept_grade": "स्वीकार करना",
|
||||||
"reject_grade": "अस्वीकार करना",
|
"reject_grade": "अस्वीकार करना",
|
||||||
"add_comment_placeholder": "एक टिप्पणी छोड़ें",
|
"add_comment_placeholder": "एक टिप्पणी छोड़ें",
|
||||||
"questions_tried": "कुल प्रयासों के कारण यह स्कोर आवंटित किया गया:"
|
"questions_tried": "कुल प्रयासों के कारण यह स्कोर आवंटित किया गया:",
|
||||||
|
"delete_prompt": "मिटाना",
|
||||||
|
"delete_error": "सबमिशन हटाने में विफल",
|
||||||
|
"delete_success": "सबमिशन सफलतापूर्वक हटा दिया गया"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attendance": {
|
"attendance": {
|
||||||
@@ -735,12 +738,6 @@
|
|||||||
"materials": "सामग्री",
|
"materials": "सामग्री",
|
||||||
"exercises": "अभ्यास"
|
"exercises": "अभ्यास"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "मिटाना",
|
|
||||||
"content": "क्या आप आश्वस्त है कि आपको डिलीट करना है:",
|
|
||||||
"no": "नहीं",
|
|
||||||
"yes": "हाँ"
|
|
||||||
},
|
|
||||||
"add_lesson": {
|
"add_lesson": {
|
||||||
"button_title": "जोड़ना",
|
"button_title": "जोड़ना",
|
||||||
"modal_heading": "नया पाठ जोड़ें",
|
"modal_heading": "नया पाठ जोड़ें",
|
||||||
@@ -1390,5 +1387,11 @@
|
|||||||
"empty_heading": "कोई पाठ्यक्रम उपलब्ध नहीं है",
|
"empty_heading": "कोई पाठ्यक्रम उपलब्ध नहीं है",
|
||||||
"empty_description": "वर्तमान में कोई प्रकाशित पाठ्यक्रम उपलब्ध नहीं है",
|
"empty_description": "वर्तमान में कोई प्रकाशित पाठ्यक्रम उपलब्ध नहीं है",
|
||||||
"heading": "हमारे पाठ्यक्रमों का अन्वेषण करें"
|
"heading": "हमारे पाठ्यक्रमों का अन्वेषण करें"
|
||||||
|
},
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "मिटाना",
|
||||||
|
"content": "क्या आपको यकीन है?",
|
||||||
|
"no": "नहीं",
|
||||||
|
"yes": "हाँ"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,10 @@
|
|||||||
"accept_grade": "Aceitar",
|
"accept_grade": "Aceitar",
|
||||||
"reject_grade": "Rejeitar",
|
"reject_grade": "Rejeitar",
|
||||||
"add_comment_placeholder": "Deixe um comentário",
|
"add_comment_placeholder": "Deixe um comentário",
|
||||||
"questions_tried": "Alocada esta pontuação por causa do total de tentativas:"
|
"questions_tried": "Alocada esta pontuação por causa do total de tentativas:",
|
||||||
|
"delete_prompt": "Excluir",
|
||||||
|
"delete_error": "Falha ao excluir o envio",
|
||||||
|
"delete_success": "Envio excluído com sucesso"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attendance": {
|
"attendance": {
|
||||||
@@ -735,12 +738,6 @@
|
|||||||
"materials": "Materiais",
|
"materials": "Materiais",
|
||||||
"exercises": "Exercícios"
|
"exercises": "Exercícios"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "Excluir",
|
|
||||||
"content": "Tem certeza de que deseja excluir:",
|
|
||||||
"no": "Não",
|
|
||||||
"yes": "Sim"
|
|
||||||
},
|
|
||||||
"add_lesson": {
|
"add_lesson": {
|
||||||
"button_title": "Adicionar",
|
"button_title": "Adicionar",
|
||||||
"modal_heading": "Adicionar nova lição",
|
"modal_heading": "Adicionar nova lição",
|
||||||
@@ -1390,5 +1387,11 @@
|
|||||||
"empty_heading": "Nenhum curso disponível",
|
"empty_heading": "Nenhum curso disponível",
|
||||||
"empty_description": "Atualmente não há nenhum curso publicado disponível",
|
"empty_description": "Atualmente não há nenhum curso publicado disponível",
|
||||||
"heading": "Explore nossos cursos"
|
"heading": "Explore nossos cursos"
|
||||||
|
},
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "Excluir",
|
||||||
|
"content": "Tem certeza?",
|
||||||
|
"no": "Não",
|
||||||
|
"yes": "Sim"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,10 @@
|
|||||||
"accept_grade": "Принимать",
|
"accept_grade": "Принимать",
|
||||||
"reject_grade": "Отклонять",
|
"reject_grade": "Отклонять",
|
||||||
"add_comment_placeholder": "Оставить комментарий",
|
"add_comment_placeholder": "Оставить комментарий",
|
||||||
"questions_tried": "Присвоен этот балл из-за общего количества попыток:"
|
"questions_tried": "Присвоен этот балл из-за общего количества попыток:",
|
||||||
|
"delete_prompt": "Удалить",
|
||||||
|
"delete_error": "Не удалось удалить отправку",
|
||||||
|
"delete_success": "Отправка успешно удалена"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attendance": {
|
"attendance": {
|
||||||
@@ -735,12 +738,6 @@
|
|||||||
"materials": "Материалы",
|
"materials": "Материалы",
|
||||||
"exercises": "Упражнения"
|
"exercises": "Упражнения"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "Удалить",
|
|
||||||
"content": "Вы уверены, что хотите удалить:",
|
|
||||||
"no": "Нет",
|
|
||||||
"yes": "Да"
|
|
||||||
},
|
|
||||||
"add_lesson": {
|
"add_lesson": {
|
||||||
"button_title": "Добавлять",
|
"button_title": "Добавлять",
|
||||||
"modal_heading": "Добавить новый урок",
|
"modal_heading": "Добавить новый урок",
|
||||||
@@ -1390,5 +1387,11 @@
|
|||||||
"empty_heading": "Нет доступных курсов",
|
"empty_heading": "Нет доступных курсов",
|
||||||
"empty_description": "На данный момент нет доступных опубликованных курсов",
|
"empty_description": "На данный момент нет доступных опубликованных курсов",
|
||||||
"heading": "Ознакомьтесь с нашими курсами"
|
"heading": "Ознакомьтесь с нашими курсами"
|
||||||
|
},
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "Удалить",
|
||||||
|
"content": "Вы уверены?",
|
||||||
|
"no": "Нет",
|
||||||
|
"yes": "Да"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,10 @@
|
|||||||
"accept_grade": "Chấp nhận",
|
"accept_grade": "Chấp nhận",
|
||||||
"reject_grade": "Từ chối",
|
"reject_grade": "Từ chối",
|
||||||
"add_comment_placeholder": "Để lại một bình luận",
|
"add_comment_placeholder": "Để lại một bình luận",
|
||||||
"questions_tried": "Phân bổ số điểm này dựa trên tổng số lần thử:"
|
"questions_tried": "Phân bổ số điểm này dựa trên tổng số lần thử:",
|
||||||
|
"delete_prompt": "Xóa bỏ",
|
||||||
|
"delete_error": "Không thể xóa bài nộp",
|
||||||
|
"delete_success": "Đã xóa bài nộp thành công"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attendance": {
|
"attendance": {
|
||||||
@@ -735,12 +738,6 @@
|
|||||||
"materials": "Nguyên vật liệu",
|
"materials": "Nguyên vật liệu",
|
||||||
"exercises": "Bài tập"
|
"exercises": "Bài tập"
|
||||||
},
|
},
|
||||||
"delete_lesson": {
|
|
||||||
"modal_heading": "Xóa bỏ",
|
|
||||||
"content": "Bạn có chắc chắn muốn xóa:",
|
|
||||||
"no": "KHÔNG",
|
|
||||||
"yes": "Đúng"
|
|
||||||
},
|
|
||||||
"add_lesson": {
|
"add_lesson": {
|
||||||
"button_title": "Thêm vào",
|
"button_title": "Thêm vào",
|
||||||
"modal_heading": "Thêm bài học mới",
|
"modal_heading": "Thêm bài học mới",
|
||||||
@@ -1390,5 +1387,11 @@
|
|||||||
"empty_heading": "Không có khóa học nào",
|
"empty_heading": "Không có khóa học nào",
|
||||||
"empty_description": "Hiện tại chưa có khóa học nào được xuất bản",
|
"empty_description": "Hiện tại chưa có khóa học nào được xuất bản",
|
||||||
"heading": "Khám phá các khóa học của chúng tôi"
|
"heading": "Khám phá các khóa học của chúng tôi"
|
||||||
|
},
|
||||||
|
"delete_modal": {
|
||||||
|
"label": "Xóa bỏ",
|
||||||
|
"content": "Bạn có chắc không?",
|
||||||
|
"no": "KHÔNG",
|
||||||
|
"yes": "Đúng"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { Profile } from '.';
|
||||||
|
|
||||||
|
export interface SubmissionItem {
|
||||||
|
id: string;
|
||||||
|
statusId: number;
|
||||||
|
isEarly: boolean;
|
||||||
|
submittedAt: string;
|
||||||
|
exercise: {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
answers: string;
|
||||||
|
student: Partial<Profile>;
|
||||||
|
lesson: {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SubmissionSection {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
value: number;
|
||||||
|
items: SubmissionItem[] | [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SubmissionIdData {
|
||||||
|
id: string;
|
||||||
|
statusId: number;
|
||||||
|
title: string;
|
||||||
|
isEarly: boolean;
|
||||||
|
questionAnswerByPoint: Record<string, string>;
|
||||||
|
answers: Record<string, string>;
|
||||||
|
questions: {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
order: number;
|
||||||
|
points: number;
|
||||||
|
question_type_id: number;
|
||||||
|
}[];
|
||||||
|
questionAnswers: {
|
||||||
|
open_answer: string;
|
||||||
|
question_id: number;
|
||||||
|
answers: [];
|
||||||
|
}[];
|
||||||
|
student?: Partial<Profile>;
|
||||||
|
feedback: string;
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
import PageBody from '$lib/components/PageBody/index.svelte';
|
import PageBody from '$lib/components/PageBody/index.svelte';
|
||||||
import Box from '$lib/components/Box/index.svelte';
|
import Box from '$lib/components/Box/index.svelte';
|
||||||
import { course, group } from '$lib/components/Course/store';
|
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 { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
|
||||||
import { ROLE } from '$lib/utils/constants/roles';
|
import { ROLE } from '$lib/utils/constants/roles';
|
||||||
import { takeAttendance } from '$lib/utils/services/attendance';
|
import { takeAttendance } from '$lib/utils/services/attendance';
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
function searchStudents(query: string, _students: GroupPerson[]) {
|
function searchStudents(query: string, _students: GroupPerson[]) {
|
||||||
const lowercaseQuery = query.toLowerCase();
|
const lowercaseQuery = query.toLowerCase();
|
||||||
return _students.filter((student) =>
|
return _students.filter((student) =>
|
||||||
student.profile.fullname.toLowerCase().includes(lowercaseQuery)
|
student.profile?.fullname?.toLowerCase()?.includes(lowercaseQuery)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,7 +272,9 @@
|
|||||||
<DateField
|
<DateField
|
||||||
value={formatDate(lesson.lesson_at)}
|
value={formatDate(lesson.lesson_at)}
|
||||||
className="p-2 my-2 rounded-md sm:w-[179px] dark:bg-neutral-800 dark:text-white"
|
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}
|
{:else}
|
||||||
<div class="mb-2 flex">
|
<div class="mb-2 flex">
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
import PageBody from '$lib/components/PageBody/index.svelte';
|
import PageBody from '$lib/components/PageBody/index.svelte';
|
||||||
import Materials from '$lib/components/Course/components/Lesson/Materials/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 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 MODES from '$lib/utils/constants/mode';
|
||||||
import { course } from '$lib/components/Course/store';
|
import { course } from '$lib/components/Course/store';
|
||||||
import Download from 'carbon-icons-svelte/lib/Download.svelte';
|
import Download from 'carbon-icons-svelte/lib/Download.svelte';
|
||||||
@@ -458,7 +458,7 @@
|
|||||||
|
|
||||||
<!-- Version Control Preview -->
|
<!-- Version Control Preview -->
|
||||||
{#if isVersionDrawerOpen && window.innerWidth >= 1024}
|
{#if isVersionDrawerOpen && window.innerWidth >= 1024}
|
||||||
<LanguageLessonVersionHistory
|
<LessonVersionHistory
|
||||||
open={isVersionDrawerOpen}
|
open={isVersionDrawerOpen}
|
||||||
on:close={() => (isVersionDrawerOpen = false)}
|
on:close={() => (isVersionDrawerOpen = false)}
|
||||||
on:restore={refetchDataAfterVersionRestore}
|
on:restore={refetchDataAfterVersionRestore}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
import { group } from '$lib/components/Course/store';
|
import { group } from '$lib/components/Course/store';
|
||||||
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
|
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
|
||||||
import { fetchExercisesByMarks } from '$lib/utils/services/courses';
|
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 { fetchMarks } from '$lib/utils/services/marks';
|
||||||
import { profile } from '$lib/utils/store/user';
|
import { profile } from '$lib/utils/store/user';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
|
|||||||
@@ -13,9 +13,10 @@
|
|||||||
import {
|
import {
|
||||||
fetchSubmissions,
|
fetchSubmissions,
|
||||||
updateSubmission,
|
updateSubmission,
|
||||||
updateQuestionAnswer
|
updateQuestionAnswer,
|
||||||
} from '$lib/utils/services/submissions/index';
|
deleteSubmission
|
||||||
import { formatAnswers } from '$lib/components/Course/function';
|
} from '$lib/utils/services/submissions';
|
||||||
|
import { formatAnswers } from '$lib/components/Course/function.js';
|
||||||
import { snackbar } from '$lib/components/Snackbar/store';
|
import { snackbar } from '$lib/components/Snackbar/store';
|
||||||
import isSubmissionEarly from '$lib/utils/functions/isSubmissionEarly';
|
import isSubmissionEarly from '$lib/utils/functions/isSubmissionEarly';
|
||||||
import formatDate from '$lib/utils/functions/formatDate';
|
import formatDate from '$lib/utils/functions/formatDate';
|
||||||
@@ -26,29 +27,11 @@
|
|||||||
import { currentOrg, currentOrgDomain } from '$lib/utils/store/org';
|
import { currentOrg, currentOrgDomain } from '$lib/utils/store/org';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
import { t } from '$lib/utils/functions/translations';
|
import { t } from '$lib/utils/functions/translations';
|
||||||
|
import type {
|
||||||
type items = {
|
SubmissionIdData,
|
||||||
id: number;
|
SubmissionItem,
|
||||||
statusId: number;
|
SubmissionSection
|
||||||
isEarly: boolean;
|
} from '$lib/utils/types/submission';
|
||||||
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[] | [];
|
|
||||||
};
|
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
const { courseId } = data;
|
const { courseId } = data;
|
||||||
@@ -58,8 +41,8 @@
|
|||||||
let lessonDetails: { id: string; title: string };
|
let lessonDetails: { id: string; title: string };
|
||||||
let totalMark = 0;
|
let totalMark = 0;
|
||||||
let maxMark = 0;
|
let maxMark = 0;
|
||||||
let submissionIdData: { [key: number]: any } = {};
|
let submissionIdData: { [key: number]: SubmissionIdData } = {};
|
||||||
let submissionId: string | number | null;
|
let submissionId: string;
|
||||||
let openExercise = false;
|
let openExercise = false;
|
||||||
let isGradeWithAI = false;
|
let isGradeWithAI = false;
|
||||||
|
|
||||||
@@ -69,7 +52,7 @@
|
|||||||
3: $t('course.navItem.submissions.submission_status.graded')
|
3: $t('course.navItem.submissions.submission_status.graded')
|
||||||
};
|
};
|
||||||
|
|
||||||
let sections: sectionType[] = [
|
let sections: SubmissionSection[] = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
title: $t('course.navItem.submissions.submission_status.submitted'),
|
title: $t('course.navItem.submissions.submission_status.submitted'),
|
||||||
@@ -104,16 +87,16 @@
|
|||||||
totalMark = calculateTotal(submissionData?.questionAnswerByPoint);
|
totalMark = calculateTotal(submissionData?.questionAnswerByPoint);
|
||||||
|
|
||||||
const { fullname, email } = submissionData?.student;
|
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 exerciseLink = `${$currentOrgDomain}/courses/${courseId}/lessons/${lessonDetails.id}/exercises/${exerciseDetails.id}`;
|
||||||
|
|
||||||
const content = `
|
const content = `
|
||||||
<p>Hello ${fullname},</p>
|
<p>Hello ${fullname},</p>
|
||||||
<p>The status of your submitted exercise on <strong>${title}</strong> has been updated to ${
|
<p>The status of your submitted exercise on <strong>${title}</strong> has been updated to ${
|
||||||
submissionStatus[status_id]
|
submissionStatus[statusId]
|
||||||
}</p>
|
}</p>
|
||||||
${
|
${
|
||||||
status_id == 3
|
statusId == 3
|
||||||
? `<p>Your score was ${totalMark}/${maxMark}</p>
|
? `<p>Your score was ${totalMark}/${maxMark}</p>
|
||||||
<a class="button" href="${exerciseLink}">View your Result</a>
|
<a class="button" href="${exerciseLink}">View your Result</a>
|
||||||
`
|
`
|
||||||
@@ -133,9 +116,9 @@
|
|||||||
|
|
||||||
function handleItemFinalize(
|
function handleItemFinalize(
|
||||||
columnIdx: number,
|
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];
|
const { id } = sections[columnIdx];
|
||||||
|
|
||||||
@@ -154,7 +137,7 @@
|
|||||||
// Update key mapping for each submission also
|
// Update key mapping for each submission also
|
||||||
submissionIdData[itemToWithNewStatus.id] = {
|
submissionIdData[itemToWithNewStatus.id] = {
|
||||||
...submissionIdData[itemToWithNewStatus.id],
|
...submissionIdData[itemToWithNewStatus.id],
|
||||||
status_id: itemToWithNewStatus.statusId
|
statusId: itemToWithNewStatus.statusId
|
||||||
};
|
};
|
||||||
|
|
||||||
notifyStudent(submissionIdData[itemToWithNewStatus.id]);
|
notifyStudent(submissionIdData[itemToWithNewStatus.id]);
|
||||||
@@ -188,12 +171,12 @@
|
|||||||
nextStatusId,
|
nextStatusId,
|
||||||
total
|
total
|
||||||
}: {
|
}: {
|
||||||
submissionId: number;
|
submissionId: string;
|
||||||
prevStatusId: number;
|
prevStatusId: number;
|
||||||
nextStatusId: number;
|
nextStatusId: number;
|
||||||
total: number;
|
total: number;
|
||||||
}) {
|
}) {
|
||||||
let itemToWithNewStatus: items | undefined;
|
let itemToWithNewStatus: SubmissionItem | undefined;
|
||||||
|
|
||||||
// Remove from current column
|
// Remove from current column
|
||||||
const { items } = sections[prevStatusId - 1];
|
const { items } = sections[prevStatusId - 1];
|
||||||
@@ -218,7 +201,7 @@
|
|||||||
// Update key mapping for each submission also
|
// Update key mapping for each submission also
|
||||||
submissionIdData[itemToWithNewStatus.id] = {
|
submissionIdData[itemToWithNewStatus.id] = {
|
||||||
...submissionIdData[itemToWithNewStatus.id],
|
...submissionIdData[itemToWithNewStatus.id],
|
||||||
status_id: itemToWithNewStatus.statusId
|
statusId: itemToWithNewStatus.statusId
|
||||||
};
|
};
|
||||||
|
|
||||||
notifyStudent(submissionIdData[itemToWithNewStatus.id]);
|
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: {
|
async function handleSave(submission: {
|
||||||
questionAnswerByPoint: any;
|
questionAnswerByPoint: any;
|
||||||
questionAnswers: any;
|
questionAnswers: any;
|
||||||
@@ -262,25 +267,19 @@
|
|||||||
await Promise.all(updates);
|
await Promise.all(updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
$: {
|
|
||||||
const query = new URLSearchParams($page.url.search);
|
|
||||||
submissionId = query.get('submissionId');
|
|
||||||
openExercise = !!submissionId && submissionIdData[submissionId];
|
|
||||||
}
|
|
||||||
|
|
||||||
async function firstRender(courseId: string) {
|
async function firstRender(courseId: string) {
|
||||||
const { data: submissions } = await fetchSubmissions(courseId);
|
const { data: submissions } = await fetchSubmissions(courseId);
|
||||||
const sectionById: { [key: number]: sectionType[] } = {};
|
const sectionById: { [key: number]: SubmissionSection[] } = {};
|
||||||
|
|
||||||
if (submissions) {
|
if (submissions) {
|
||||||
for (const submission of submissions) {
|
for (const submission of submissions) {
|
||||||
const { id, created_at, exercise, course, answers, groupmember, status_id, feedback } =
|
const { id, created_at, answers, groupmember, feedback, exercise } = submission;
|
||||||
submission;
|
|
||||||
|
|
||||||
const isEarly = isSubmissionEarly(created_at, exercise.due_by);
|
const isEarly = isSubmissionEarly(created_at, exercise.due_by);
|
||||||
|
|
||||||
const submissionItem = {
|
const submissionItem = {
|
||||||
id,
|
id,
|
||||||
statusId: status_id,
|
statusId: submission.status_id,
|
||||||
isEarly,
|
isEarly,
|
||||||
feedback,
|
feedback,
|
||||||
submittedAt: formatDate(created_at),
|
submittedAt: formatDate(created_at),
|
||||||
@@ -295,14 +294,17 @@
|
|||||||
title: exercise.lesson.title
|
title: exercise.lesson.title
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exerciseDetails = { id: submissionItem.exercise.id, title: submissionItem.exercise.title };
|
exerciseDetails = { id: submissionItem.exercise.id, title: submissionItem.exercise.title };
|
||||||
|
|
||||||
lessonDetails = {
|
lessonDetails = {
|
||||||
id: submissionItem.lesson.id,
|
id: submissionItem.lesson.id,
|
||||||
title: submissionItem.lesson.title
|
title: submissionItem.lesson.title
|
||||||
};
|
};
|
||||||
|
|
||||||
submissionIdData[id] = {
|
submissionIdData[id] = {
|
||||||
id,
|
id,
|
||||||
status_id,
|
statusId: submissionItem.statusId,
|
||||||
feedback,
|
feedback,
|
||||||
isEarly,
|
isEarly,
|
||||||
title: exercise.title,
|
title: exercise.title,
|
||||||
@@ -317,10 +319,10 @@
|
|||||||
}, {})
|
}, {})
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Array.isArray(sectionById[status_id])) {
|
if (Array.isArray(sectionById[submission.status_id])) {
|
||||||
sectionById[status_id].push(submissionItem);
|
sectionById[submission.status_id].push(submissionItem);
|
||||||
} else {
|
} else {
|
||||||
sectionById[status_id] = [submissionItem];
|
sectionById[submission.status_id] = [submissionItem];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,6 +335,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$: browser && $course.id && firstRender($course.id);
|
$: browser && $course.id && firstRender($course.id);
|
||||||
|
$: {
|
||||||
|
const query = new URLSearchParams($page.url.search);
|
||||||
|
submissionId = query.get('submissionId') ?? '';
|
||||||
|
openExercise = !!submissionId && submissionIdData[submissionId];
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<MarkExerciseModal
|
<MarkExerciseModal
|
||||||
@@ -341,7 +348,7 @@
|
|||||||
data={submissionIdData[submissionId] || {}}
|
data={submissionIdData[submissionId] || {}}
|
||||||
{handleSave}
|
{handleSave}
|
||||||
{updateStatus}
|
{updateStatus}
|
||||||
{submissionId}
|
deleteSubmission={handleDeleteSubmission}
|
||||||
bind:isGradeWithAI
|
bind:isGradeWithAI
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -403,7 +410,6 @@
|
|||||||
>
|
>
|
||||||
<p class="dark:text-white text-grey text-sm">
|
<p class="dark:text-white text-grey text-sm">
|
||||||
#{item.lesson.title}
|
#{item.lesson.title}
|
||||||
{`${item.tutor ? 'created by' + item.tutor.name : ''}`}
|
|
||||||
</p>
|
</p>
|
||||||
</a>
|
</a>
|
||||||
<p class="dark:text-white text-gray-500 text-xs">
|
<p class="dark:text-white text-gray-500 text-xs">
|
||||||
|
|||||||
Reference in New Issue
Block a user