Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio
This commit is contained in:
+56
-21
@@ -1,4 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { Loading } from 'carbon-components-svelte';
|
||||||
|
import type { ExerciseSubmissions } from '$lib/utils/types';
|
||||||
import { questionnaire } from '../../store/exercise';
|
import { questionnaire } from '../../store/exercise';
|
||||||
import { submissions } from './store';
|
import { submissions } from './store';
|
||||||
|
|
||||||
@@ -9,18 +11,49 @@
|
|||||||
|
|
||||||
let studentSelected = 0;
|
let studentSelected = 0;
|
||||||
|
|
||||||
const isSelected = (option: { value: string[] }): boolean => {
|
const isSelected = (
|
||||||
|
student: ExerciseSubmissions,
|
||||||
|
option: { question_id: number; value: string[] }
|
||||||
|
) => {
|
||||||
if ($submissions) {
|
if ($submissions) {
|
||||||
let submittedAnswer = $submissions[studentSelected]?.answers.map((answer) => answer.answers);
|
let submittedAnswer = student?.answers;
|
||||||
return !!submittedAnswer.find((opt) => opt == option.value);
|
let filteredAnswer = submittedAnswer.filter(
|
||||||
|
(ans: { question_id: number }) => ans.question_id === option.question_id
|
||||||
|
);
|
||||||
|
if (filteredAnswer.map((ans) => ans.answers.length > 1)) {
|
||||||
|
return filteredAnswer.some((ans) => ans.answers.includes(option.value));
|
||||||
|
} else {
|
||||||
|
return filteredAnswer.map((ans: { answers: any }) => ans.answers) == option.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return false;
|
const isCorrect = (
|
||||||
|
student: ExerciseSubmissions,
|
||||||
|
option: { is_correct?: any; question_id?: number; value?: string[] }
|
||||||
|
) => {
|
||||||
|
if (!isSelected(student, option)) return;
|
||||||
|
if (option.is_correct) {
|
||||||
|
return 'border-green-700';
|
||||||
|
} else {
|
||||||
|
return 'border-red-700';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getOpenAnswer = (student: ExerciseSubmissions, q: never) => {
|
||||||
|
let submittedAnswer = student?.answers;
|
||||||
|
let filteredAnswer = submittedAnswer.filter(
|
||||||
|
(ans: { question_id: number }) => ans.question_id === q.id
|
||||||
|
);
|
||||||
|
if (filteredAnswer.some((ans: { open_answer: string }) => ans.open_answer == '')) {
|
||||||
|
return 'No Answer was provided';
|
||||||
|
} else {
|
||||||
|
return filteredAnswer.map((ans: { open_answer: any }) => ans.open_answer);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isLoading}
|
{#if isLoading}
|
||||||
Loading data
|
<Loading withOverlay={true} />
|
||||||
{:else if $submissions?.length}
|
{:else if $submissions?.length}
|
||||||
<div class="flex gap-1 w-full overflow-auto mt-2 mb-5">
|
<div class="flex gap-1 w-full overflow-auto mt-2 mb-5">
|
||||||
{#each $submissions as student, i}
|
{#each $submissions as student, i}
|
||||||
@@ -52,28 +85,30 @@
|
|||||||
{#if $questionnaire.questions}
|
{#if $questionnaire.questions}
|
||||||
{#each $questionnaire.questions as q, i}
|
{#each $questionnaire.questions as q, i}
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<p>{i + 1}. {q.title}</p>
|
<h3>{i + 1}. {q.title}</h3>
|
||||||
{#if q.question_type_id !== 3}
|
{#if q.question_type_id !== 3}
|
||||||
{#each q.options as option, i}
|
{#each q.options as option, i}
|
||||||
<div
|
<div
|
||||||
class="flex gap-2 max-w-[80%] items-center my-1 border border-gray-600 dark:border-gray-100 rounded-md p-3"
|
class={`flex gap-2 items-center my-2 border-2 border-gray-300 rounded-md p-2 ${isCorrect(
|
||||||
|
$submissions[studentSelected],
|
||||||
|
option
|
||||||
|
)}`}
|
||||||
>
|
>
|
||||||
<input type="checkbox" name="" id="" checked={isSelected(option)} />
|
<input
|
||||||
<p>{option.label}</p>
|
type="radio"
|
||||||
|
name=""
|
||||||
|
id=""
|
||||||
|
class="form-radio"
|
||||||
|
checked={isSelected($submissions[studentSelected], option)}
|
||||||
|
/>
|
||||||
|
<span class="dark:text-white">{option.label}</span>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{:else}
|
||||||
{#if q.question_type_id === 3}
|
<div class="rounded bg-slate-100 dark:bg-slate-300 p-2 my-1 w-full">
|
||||||
<div
|
<span class="text-base font-medium text-black">
|
||||||
class="border border-gray-300 rounded-md max-w-[80%] bg-slate-200 dark:bg-slate-500 p-2 my-1"
|
{getOpenAnswer($submissions[studentSelected], q)}
|
||||||
>
|
</span>
|
||||||
{#if $submissions[studentSelected].answers.map((ans) => ans.open_answer)}
|
|
||||||
<p>
|
|
||||||
{$submissions[studentSelected].answers.map((ans) => ans.open_answer)}
|
|
||||||
</p>
|
|
||||||
{:else}
|
|
||||||
<p>No answer</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
import { getChartOptions } from './functions';
|
import { getChartOptions } from './functions';
|
||||||
import { submissions } from './store';
|
import { submissions } from './store';
|
||||||
import '@carbon/charts-svelte/styles.css';
|
import '@carbon/charts-svelte/styles.css';
|
||||||
|
import { Loading } from 'carbon-components-svelte';
|
||||||
|
|
||||||
export let isLoading = true;
|
export let isLoading = true;
|
||||||
|
|
||||||
@@ -138,7 +139,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isLoading}
|
{#if isLoading}
|
||||||
Loading data
|
<Loading withOverlay={true} />
|
||||||
{:else if browser}
|
{:else if browser}
|
||||||
<div>
|
<div>
|
||||||
<h1>Question Charts</h1>
|
<h1>Question Charts</h1>
|
||||||
@@ -150,14 +151,12 @@
|
|||||||
{:else if q.type === 2}
|
{:else if q.type === 2}
|
||||||
<svelte:component this={barChart} data={q.chartData} options={barOptions} />
|
<svelte:component this={barChart} data={q.chartData} options={barOptions} />
|
||||||
{:else}
|
{:else}
|
||||||
<div class="max-h-[200px] overflow-auto">
|
<div class="max-h-[250px] overflow-auto">
|
||||||
<ul>
|
<ul>
|
||||||
{#each q.chartData as answer (answer)}
|
{#each q.chartData as answer (answer)}
|
||||||
{#if answer.group}
|
{#if answer.group}
|
||||||
<div
|
<div class="rounded bg-slate-100 dark:bg-slate-300 p-2 my-1 w-full">
|
||||||
class="border border-gray-300 rounded-md w-[80%] bg-slate-200 dark:bg-slate-500 p-2 my-1"
|
<li class="text-base font-medium text-black">{answer.group}</li>
|
||||||
>
|
|
||||||
<li>{answer.group}</li>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -58,13 +58,12 @@ export function getPropsForQuestion(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: questionIndex + '. ' + question.title,
|
index: questionIndex + '. ',
|
||||||
|
title: question.title,
|
||||||
name: `${question.name}`,
|
name: `${question.name}`,
|
||||||
options: question.options,
|
options: question.options,
|
||||||
code: question.code,
|
code: question.code,
|
||||||
defaultValue: isOpenQuesiton
|
defaultValue: isOpenQuesiton ? answers[question.name] || '' : answers[question.name] || [],
|
||||||
? answers[question.name] || ''
|
|
||||||
: answers[question.name] || [],
|
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onPrevious,
|
onPrevious,
|
||||||
disablePreviousButton: questionIndex === 1,
|
disablePreviousButton: questionIndex === 1,
|
||||||
@@ -75,18 +74,18 @@ export function getPropsForQuestion(
|
|||||||
nextButtonProps: isOpenQuesiton
|
nextButtonProps: isOpenQuesiton
|
||||||
? {
|
? {
|
||||||
label: 'Next',
|
label: 'Next',
|
||||||
isActive: true,
|
isActive: true
|
||||||
}
|
}
|
||||||
: isCorrect
|
: isCorrect
|
||||||
? {
|
? {
|
||||||
label: isLast ? 'Finish' : 'Next',
|
label: isLast ? 'Finish' : 'Next',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
disableOptionSelect: true,
|
disableOptionSelect: true
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
label: 'Check',
|
label: 'Check',
|
||||||
isActive: false,
|
isActive: false
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import Grade from '$lib/components/Question/Grade.svelte';
|
import Grade from '$lib/components/Question/Grade.svelte';
|
||||||
|
|
||||||
export let title = '';
|
export let title = '';
|
||||||
|
export let index = 1;
|
||||||
export let code;
|
export let code;
|
||||||
export let name = '';
|
export let name = '';
|
||||||
export let options = [];
|
export let options = [];
|
||||||
@@ -63,7 +64,12 @@
|
|||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<HtmlRender className="mt-4">
|
<HtmlRender className="mt-4">
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
<h3 class={typeof grade === 'number' ? 'w-3/4' : ''}>{title}</h3>
|
<span class={`${typeof grade === 'number' ? 'w-3/4' : ''} flex gap-1`}>
|
||||||
|
<h3>{index}</h3>
|
||||||
|
<h3>
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
</span>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</HtmlRender>
|
</HtmlRender>
|
||||||
<Grade {gradeMax} {grade} {disableGrading} />
|
<Grade {gradeMax} {grade} {disableGrading} />
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import Grade from '$lib/components/Question/Grade.svelte';
|
import Grade from '$lib/components/Question/Grade.svelte';
|
||||||
|
|
||||||
export let title = '';
|
export let title = '';
|
||||||
|
export let index = 1;
|
||||||
export let code = '';
|
export let code = '';
|
||||||
export let name = '';
|
export let name = '';
|
||||||
export let options = [];
|
export let options = [];
|
||||||
@@ -65,9 +66,12 @@
|
|||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<HtmlRender className="mt-4">
|
<HtmlRender className="mt-4">
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
<h3 class="dark:text-white {labelClassName} {typeof grade === 'number' && 'w-3/4'}">
|
<span
|
||||||
{title}
|
class="dark:text-white flex gap-1 {labelClassName} {typeof grade === 'number' && 'w-3/4'}"
|
||||||
</h3>
|
>
|
||||||
|
<h3>{index}</h3>
|
||||||
|
<h3>{title}</h3>
|
||||||
|
</span>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</HtmlRender>
|
</HtmlRender>
|
||||||
<Grade {gradeMax} {grade} {disableGrading} />
|
<Grade {gradeMax} {grade} {disableGrading} />
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import Grade from '$lib/components/Question/Grade.svelte';
|
import Grade from '$lib/components/Question/Grade.svelte';
|
||||||
|
|
||||||
export let title = '';
|
export let title = '';
|
||||||
|
export let index = 1;
|
||||||
export let code = '';
|
export let code = '';
|
||||||
export let name = '';
|
export let name = '';
|
||||||
export let onSubmit = () => {};
|
export let onSubmit = () => {};
|
||||||
@@ -37,7 +38,10 @@
|
|||||||
<div class="flex items-center justify-between mb-2">
|
<div class="flex items-center justify-between mb-2">
|
||||||
<HtmlRender className="mt-4">
|
<HtmlRender className="mt-4">
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
<h3 class={typeof grade === 'number' ? 'w-3/4' : ''}>{title}</h3>
|
<span class={`${typeof grade === 'number' ? 'w-3/4' : ''} flex gap-1`}>
|
||||||
|
<h3>{index}</h3>
|
||||||
|
<h3>{title}</h3>
|
||||||
|
</span>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</HtmlRender>
|
</HtmlRender>
|
||||||
<Grade {gradeMax} {grade} {disableGrading} />
|
<Grade {gradeMax} {grade} {disableGrading} />
|
||||||
|
|||||||
Reference in New Issue
Block a user