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,6 +126,27 @@
width="w-2/4" width="w-2/4"
modalHeading="Update description" modalHeading="Update description"
> >
{#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> <div>
<QuestionContainer isTitle={true}> <QuestionContainer isTitle={true}>
<TextField <TextField
@@ -130,7 +172,16 @@
onInputChange={() => ($questionnaire.is_description_dirty = true)} onInputChange={() => ($questionnaire.is_description_dirty = true)}
/> />
</QuestionContainer> </QuestionContainer>
<div class="float-right">
<PrimaryButton
className="px-6 py-2"
variant={VARIANTS.CONTAINED_DANGER}
label="Delete this exercise"
onClick={() => (shouldDelete = true)}
/>
</div> </div>
</div>
{/if}
</Modal> </Modal>
<div class="w-full"> <div class="w-full">
@@ -230,7 +230,6 @@
<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>
@@ -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,6 +80,7 @@
.eq('id', exerciseId) .eq('id', exerciseId)
.single(); .single();
if (data && Array.isArray(data.questions)) {
// Need to set the question type inorder for the select in the questionnaire builder to match // Need to set the question type inorder for the select in the questionnaire builder to match
data.questions.forEach((question) => { data.questions.forEach((question) => {
question.question_type = QUESTION_TYPES.find( question.question_type = QUESTION_TYPES.find(
@@ -87,6 +89,9 @@
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 });
}