CLASSROOMIO-T-15: Delete exercise

This commit is contained in:
Rotimi Best
2021-10-18 21:33:31 +03:00
parent a4aec1a2da
commit 3feee7165a
5 changed files with 119 additions and 41 deletions
@@ -36,7 +36,8 @@
QUESTION_TYPES, QUESTION_TYPES,
} from '../../../../Question/constants'; } from '../../../../Question/constants';
import { filterOutDeleted } from './functions'; import { filterOutDeleted } from './functions';
import Date from '../../../../Form/Date.svelte'; import { deleteExercise } from '../../../../../utils/services/courses';
import { lesson } from '../store/lessons';
// import EditContent from "../../../../EditContent/index.svelte"; // import EditContent from "../../../../EditContent/index.svelte";
// import readme from "../../readme.js"; // import readme from "../../readme.js";
@@ -45,10 +46,14 @@
const initialQuestionsLength = $questionnaire.questions.length; const initialQuestionsLength = $questionnaire.questions.length;
export let editDescription = false; export let editDescription = false;
export let exerciseId;
export let goBack = () => {};
let errors = {}; let errors = {};
let questionIdToDelete = null; let questionIdToDelete = null;
let questions = []; let questions = [];
let shouldDelete = false;
let isDeleting = false;
function shouldScrollToLast(questionId, questions) { function shouldScrollToLast(questionId, questions) {
const currentQuestionsLength = questions.length; const currentQuestionsLength = questions.length;
@@ -88,6 +93,22 @@
return errors[question.id] ? errors[question.id][errorKey] : null; return errors[question.id] ? errors[question.id][errorKey] : null;
} }
async function handleDelete() {
console.log('delete');
isDeleting = true;
await deleteExercise(questions, exerciseId);
lesson.update((_lesson) => ({
..._lesson,
exercises: _lesson.exercises.filter(
(exercise) => exercise.id !== exerciseId
),
}));
shouldDelete = false;
goBack();
}
$: errors = $questionnaireValidation; $: errors = $questionnaireValidation;
$: questions = filterOutDeleted($questionnaire.questions); $: questions = filterOutDeleted($questionnaire.questions);
</script> </script>
@@ -105,32 +126,62 @@
width="w-2/4" width="w-2/4"
modalHeading="Update description" modalHeading="Update description"
> >
<div> {#if shouldDelete}
<QuestionContainer isTitle={true}> <form on:submit|preventDefault={() => (shouldDelete = false)}>
<TextField <h1 class="text-2xl">Are you sure?</h1>
placeholder="Title"
bind:value={$questionnaire.title} <div class="mt-5 flex items-center justify-between">
className="mb-2" <PrimaryButton
onChange={() => ($questionnaire.is_title_dirty = true)} className="px-6 py-2"
/> variant={VARIANTS.OUTLINED}
<DateTime label="No, cancel"
label="Due by" type="submit"
className="w-50" />
value={$questionnaire.due_by} <PrimaryButton
onInput={(e) => { className="px-6 py-2"
$questionnaire.due_by = e.target.value; variant={VARIANTS.CONTAINED_DANGER}
$questionnaire.is_due_by_dirty = true; label={isDeleting ? 'Deleting...' : 'Yes, delete'}
}} isDisabled={isDeleting}
/> onClick={handleDelete}
<EditContent />
writeLabel="Description" </div>
bind:value={$questionnaire.description} </form>
placeholder="Start typing your lesson" {:else}
textAreaHeight="100px" <div>
onInputChange={() => ($questionnaire.is_description_dirty = true)} <QuestionContainer isTitle={true}>
/> <TextField
</QuestionContainer> placeholder="Title"
</div> bind:value={$questionnaire.title}
className="mb-2"
onChange={() => ($questionnaire.is_title_dirty = true)}
/>
<DateTime
label="Due by"
className="w-50"
value={$questionnaire.due_by}
onInput={(e) => {
$questionnaire.due_by = e.target.value;
$questionnaire.is_due_by_dirty = true;
}}
/>
<EditContent
writeLabel="Description"
bind:value={$questionnaire.description}
placeholder="Start typing your lesson"
textAreaHeight="100px"
onInputChange={() => ($questionnaire.is_description_dirty = true)}
/>
</QuestionContainer>
<div class="float-right">
<PrimaryButton
className="px-6 py-2"
variant={VARIANTS.CONTAINED_DANGER}
label="Delete this exercise"
onClick={() => (shouldDelete = true)}
/>
</div>
</div>
{/if}
</Modal> </Modal>
<div class="w-full"> <div class="w-full">
@@ -230,13 +230,12 @@
<span <span
class="status-text bg-green-700 text-white rounded-full py-2 px-6 text-center" class="status-text bg-green-700 text-white rounded-full py-2 px-6 text-center"
title="Status: Pending Review" title="Status: Pending Review"
> >
Graded Graded
</span> </span>
{:else} {:else}
<span <span
class=" status-text bg-yellow-600 text-white rounded-full py-2 px-6 text-center" class="status-text bg-yellow-600 text-white rounded-full py-2 px-6 text-center"
title="Status: Pending Review" title="Status: Pending Review"
> >
Pending Pending
@@ -245,7 +244,7 @@
</div> </div>
{#if STATUS.GRADED === $questionnaireMetaData.status} {#if STATUS.GRADED === $questionnaireMetaData.status}
<span <span
class="border-2 border-gray-700 rounded-full h-24 w-24 flex items-center justify-center text-2xl" class="p-5 border-2 border-gray-700 rounded-full h-24 w-24 flex items-center justify-center text-2xl"
title="Status: Pending Review" title="Status: Pending Review"
> >
{$questionnaireMetaData.finalTotalGrade}/{$questionnaireMetaData.totalPossibleGrade} {$questionnaireMetaData.finalTotalGrade}/{$questionnaireMetaData.totalPossibleGrade}
@@ -25,6 +25,7 @@
export let exerciseId; export let exerciseId;
export let refetchExercise = () => {}; export let refetchExercise = () => {};
export let goBack = () => {};
let mode = MODES.view; let mode = MODES.view;
let preview = false; let preview = false;
@@ -135,7 +136,7 @@
</svelte:fragment> </svelte:fragment>
{#if mode === MODES.edit && !preview} {#if mode === MODES.edit && !preview}
<EditMode bind:editDescription /> <EditMode bind:editDescription {exerciseId} {goBack} />
{:else} {:else}
<ViewMode {preview} {exerciseId} /> <ViewMode {preview} {exerciseId} />
{/if} {/if}
@@ -1,4 +1,5 @@
<script> <script>
import { goto } from '@sapper/app';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import AudioConsole32 from 'carbon-icons-svelte/lib/AudioConsole32'; import AudioConsole32 from 'carbon-icons-svelte/lib/AudioConsole32';
import Box from '../../../../Box/index.svelte'; import Box from '../../../../Box/index.svelte';
@@ -79,14 +80,18 @@
.eq('id', exerciseId) .eq('id', exerciseId)
.single(); .single();
// Need to set the question type inorder for the select in the questionnaire builder to match if (data && Array.isArray(data.questions)) {
data.questions.forEach((question) => { // Need to set the question type inorder for the select in the questionnaire builder to match
question.question_type = QUESTION_TYPES.find( data.questions.forEach((question) => {
(type) => type.id === question.question_type.id question.question_type = QUESTION_TYPES.find(
); (type) => type.id === question.question_type.id
return question; );
}); return question;
data.questions = data.questions.sort((a, b) => a.order - b.order); });
data.questions = data.questions.sort((a, b) => a.order - b.order);
} else {
data.questions = [];
}
data.is_title_dirty = false; data.is_title_dirty = false;
data.is_description_dirty = false; data.is_description_dirty = false;
@@ -98,6 +103,10 @@
isQuestionnaireFetching.update(() => false); isQuestionnaireFetching.update(() => false);
} }
function goBack() {
goto(path);
}
onMount(() => { onMount(() => {
getExercises(); getExercises();
}); });
@@ -106,7 +115,11 @@
</script> </script>
{#if exerciseId} {#if exerciseId}
<Exercise {exerciseId} refetchExercise={() => getExercise(exerciseId)} /> <Exercise
{exerciseId}
{goBack}
refetchExercise={() => getExercise(exerciseId)}
/>
{:else} {:else}
<Modal <Modal
onClose={handleCancelAddExercise} onClose={handleCancelAddExercise}
+15 -1
View File
@@ -250,7 +250,7 @@ export async function upsertExercise(questionnaire, exerciseId) {
const res = await supabase.from('question').upsert(newQuestion); const res = await supabase.from('question').upsert(newQuestion);
if (res.error) { if (res.error) {
console.error(`Upsert question`, error); console.error(`Upsert question`, res.error);
} }
questionSupabaseRes = Array.isArray(res.data) ? res.data[0] : null; questionSupabaseRes = Array.isArray(res.data) ? res.data[0] : null;
} else { } else {
@@ -358,3 +358,17 @@ export async function submitExercise(
const res = await supabase.from('question_answer').insert(questionAnswers); const res = await supabase.from('question_answer').insert(questionAnswers);
console.log(`res`, res); console.log(`res`, res);
} }
export async function deleteExercise(questions, exerciseId) {
for (const question of questions) {
const { id } = question;
await supabase.from('option').delete().match({ question_id: id });
await supabase.from('question_answer').delete().match({ question_id: id });
await supabase.from('question').delete().match({ id });
}
await supabase.from('submission').delete().match({ exercise_id: exerciseId });
await supabase.from('exercise').delete().match({ id: exerciseId });
}