CLASSROOMIO-T-15: Delete exercise
This commit is contained in:
@@ -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}
|
||||||
|
|||||||
@@ -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 });
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user