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,
} from '../../../../Question/constants';
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 readme from "../../readme.js";
@@ -45,10 +46,14 @@
const initialQuestionsLength = $questionnaire.questions.length;
export let editDescription = false;
export let exerciseId;
export let goBack = () => {};
let errors = {};
let questionIdToDelete = null;
let questions = [];
let shouldDelete = false;
let isDeleting = false;
function shouldScrollToLast(questionId, questions) {
const currentQuestionsLength = questions.length;
@@ -88,6 +93,22 @@
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;
$: questions = filterOutDeleted($questionnaire.questions);
</script>
@@ -105,32 +126,62 @@
width="w-2/4"
modalHeading="Update description"
>
<div>
<QuestionContainer isTitle={true}>
<TextField
placeholder="Title"
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>
{#if shouldDelete}
<form on:submit|preventDefault={() => (shouldDelete = false)}>
<h1 class="text-2xl">Are you sure?</h1>
<div class="mt-5 flex items-center justify-between">
<PrimaryButton
className="px-6 py-2"
variant={VARIANTS.OUTLINED}
label="No, cancel"
type="submit"
/>
<PrimaryButton
className="px-6 py-2"
variant={VARIANTS.CONTAINED_DANGER}
label={isDeleting ? 'Deleting...' : 'Yes, delete'}
isDisabled={isDeleting}
onClick={handleDelete}
/>
</div>
</form>
{:else}
<div>
<QuestionContainer isTitle={true}>
<TextField
placeholder="Title"
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>
<div class="w-full">
@@ -230,13 +230,12 @@
<span
class="status-text bg-green-700 text-white rounded-full py-2 px-6 text-center"
title="Status: Pending Review"
>
Graded
</span>
{:else}
<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"
>
Pending
@@ -245,7 +244,7 @@
</div>
{#if STATUS.GRADED === $questionnaireMetaData.status}
<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"
>
{$questionnaireMetaData.finalTotalGrade}/{$questionnaireMetaData.totalPossibleGrade}
@@ -25,6 +25,7 @@
export let exerciseId;
export let refetchExercise = () => {};
export let goBack = () => {};
let mode = MODES.view;
let preview = false;
@@ -135,7 +136,7 @@
</svelte:fragment>
{#if mode === MODES.edit && !preview}
<EditMode bind:editDescription />
<EditMode bind:editDescription {exerciseId} {goBack} />
{:else}
<ViewMode {preview} {exerciseId} />
{/if}
@@ -1,4 +1,5 @@
<script>
import { goto } from '@sapper/app';
import { onMount } from 'svelte';
import AudioConsole32 from 'carbon-icons-svelte/lib/AudioConsole32';
import Box from '../../../../Box/index.svelte';
@@ -79,14 +80,18 @@
.eq('id', exerciseId)
.single();
// Need to set the question type inorder for the select in the questionnaire builder to match
data.questions.forEach((question) => {
question.question_type = QUESTION_TYPES.find(
(type) => type.id === question.question_type.id
);
return question;
});
data.questions = data.questions.sort((a, b) => a.order - b.order);
if (data && Array.isArray(data.questions)) {
// Need to set the question type inorder for the select in the questionnaire builder to match
data.questions.forEach((question) => {
question.question_type = QUESTION_TYPES.find(
(type) => type.id === question.question_type.id
);
return question;
});
data.questions = data.questions.sort((a, b) => a.order - b.order);
} else {
data.questions = [];
}
data.is_title_dirty = false;
data.is_description_dirty = false;
@@ -98,6 +103,10 @@
isQuestionnaireFetching.update(() => false);
}
function goBack() {
goto(path);
}
onMount(() => {
getExercises();
});
@@ -106,7 +115,11 @@
</script>
{#if exerciseId}
<Exercise {exerciseId} refetchExercise={() => getExercise(exerciseId)} />
<Exercise
{exerciseId}
{goBack}
refetchExercise={() => getExercise(exerciseId)}
/>
{:else}
<Modal
onClose={handleCancelAddExercise}
+15 -1
View File
@@ -250,7 +250,7 @@ export async function upsertExercise(questionnaire, exerciseId) {
const res = await supabase.from('question').upsert(newQuestion);
if (res.error) {
console.error(`Upsert question`, error);
console.error(`Upsert question`, res.error);
}
questionSupabaseRes = Array.isArray(res.data) ? res.data[0] : null;
} else {
@@ -358,3 +358,17 @@ export async function submitExercise(
const res = await supabase.from('question_answer').insert(questionAnswers);
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 });
}