CLASSROOMIO-T-4: Add deadline and show it was late or early

This commit is contained in:
rotimi-best
2021-09-24 13:20:40 +03:00
parent d368fc6f8d
commit 6e24435a9f
10 changed files with 101 additions and 15 deletions
@@ -35,6 +35,7 @@
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 EditContent from "../../../../EditContent/index.svelte"; // import EditContent from "../../../../EditContent/index.svelte";
// import readme from "../../readme.js"; // import readme from "../../readme.js";
@@ -100,11 +101,12 @@
/> />
<DateTime <DateTime
label="Due by" label="Due by"
bind:value={$questionnaire.due_by}
placeholder="2021-03-25"
className="w-50" className="w-50"
useTime={true} value={$questionnaire.due_by}
onChange={() => ($questionnaire.is_due_by_dirty = true)} onInput={(e) => {
$questionnaire.due_by = e.target.value;
$questionnaire.is_due_by_dirty = true;
}}
/> />
<EditContent <EditContent
writeLabel="Description" writeLabel="Description"
@@ -116,7 +116,22 @@
<div <div
class="hover:bg-gray-100 border-b border-t-0 border-l-0 border-r-0 border-gray-300 p-3" class="hover:bg-gray-100 border-b border-t-0 border-l-0 border-r-0 border-gray-300 p-3"
> >
<p class="font-bold text-lg">Details</p> <p class="font-bold text-lg">
Details
{#if data.isEarly}
<span
class="ml-2 text-sm badge rounded-sm px-2 bg-green-500 text-white"
>
early
</span>
{:else}
<span
class="ml-2 badge text-sm rounded-sm px-2 bg-red-500 text-white"
>
late
</span>
{/if}
</p>
</div> </div>
<div class="flex items-center text-sm p-3"> <div class="flex items-center text-sm p-3">
@@ -148,3 +163,9 @@
</div> </div>
</div> </div>
</Modal> </Modal>
<style>
.badge {
width: fit-content;
}
</style>
@@ -1,4 +1,5 @@
<script> <script>
import marked from 'marked';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { group, course } from '../../../store'; import { group, course } from '../../../store';
import { questionnaire } from '../store/exercise'; import { questionnaire } from '../store/exercise';
@@ -198,14 +199,23 @@
</p> </p>
| |
<p class="mx-2">All required</p> <p class="mx-2">All required</p>
{#if $questionnaire.due_by}
|
<p class="mx-2">
<strong>Due by:</strong>
{new Date($questionnaire.due_by).toLocaleString()}
</p>
{/if}
</div> </div>
<p class="text-lg mt-3">{$questionnaire.description}</p> <article class="preview prose prose-sm sm:prose p-2">
{@html marked($questionnaire.description || 'No desription')}
</article>
<PrimaryButton <PrimaryButton
onClick={handleStart} onClick={handleStart}
label="Start" label="Start"
className="my-5" className="my-5 float-right"
type="button" type="button"
/> />
</div> </div>
+3 -2
View File
@@ -3,16 +3,17 @@
export let placeholder; export let placeholder;
export let value; export let value;
export let className = ''; export let className = '';
export let onChange = () => {}; // This is to know if element is 'dirty' export let onInput = () => {};
$: console.log(`value`, value);
</script> </script>
<label class="block {className}"> <label class="block {className}">
<span class="text-gray-700">{label}</span> <span class="text-gray-700">{label}</span>
<input <input
bind:value bind:value
on:input={onInput}
{placeholder} {placeholder}
type="datetime-local" type="datetime-local"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
on:blur={onChange}
/> />
</label> </label>
+1
View File
@@ -142,6 +142,7 @@
a { a {
text-decoration: none; text-decoration: none;
color: var(--main-primary-color);
padding: 0 1.5em; padding: 0 1.5em;
font-weight: 700; font-weight: 700;
display: flex; display: flex;
+4
View File
@@ -61,6 +61,10 @@
fill: var(--main-primary-color); fill: var(--main-primary-color);
} }
.prose a {
color: var(--main-primary-color);
}
.success :global(svg.carbon-icon) { .success :global(svg.carbon-icon) {
fill: green; fill: green;
} }
+33 -5
View File
@@ -25,6 +25,9 @@
import { formatAnswers } from '../../../components/Course/function'; import { formatAnswers } from '../../../components/Course/function';
import { snackbarStore } from '../../../components/Snackbar/store'; import { snackbarStore } from '../../../components/Snackbar/store';
import { SNACKBAR_SEVERITY } from '../../../components/Snackbar/constants'; import { SNACKBAR_SEVERITY } from '../../../components/Snackbar/constants';
import Date from '../../../components/Form/Date.svelte';
import isSubmissionEarly from '../../../utils/functions/isSubmissionEarly';
import formatDate from '../../../utils/functions/formatDate';
const flipDurationMs = 300; const flipDurationMs = 300;
@@ -188,12 +191,22 @@
const sectionById = {}; const sectionById = {};
for (const submission of submissions) { for (const submission of submissions) {
const { id, exercise, course, answers, groupmember, status_id } = const {
submission; id,
created_at,
exercise,
course,
answers,
groupmember,
status_id,
} = submission;
const isEarly = isSubmissionEarly(created_at, exercise.due_by);
const submissionItem = { const submissionItem = {
id, id,
statusId: status_id, statusId: status_id,
isEarly,
submittedAt: formatDate(created_at),
exercise: { exercise: {
id: exercise.id, id: exercise.id,
title: exercise.title, title: exercise.title,
@@ -205,10 +218,11 @@
title: exercise.lesson.title, title: exercise.lesson.title,
}, },
}; };
console.log(`answers`, answers);
submissionIdData[id] = { submissionIdData[id] = {
id, id,
status_id, status_id,
isEarly,
title: exercise.title, title: exercise.title,
student: submissionItem.student, student: submissionItem.student,
questions: exercise.questions, questions: exercise.questions,
@@ -281,11 +295,16 @@
> >
{#each items as item (item.id)} {#each items as item (item.id)}
<div <div
class="border border-grey-700 w-full my-2 mx-0 rounded-md bg-white py-2 px-3" class="border {item.isEarly
? 'border-grey-700'
: 'border-red-700'} w-full my-2 mx-0 rounded-md bg-white py-2 px-3"
animate:flip={{ duration: flipDurationMs }} animate:flip={{ duration: flipDurationMs }}
> >
<div <div
class="flex items-center no-underline hover:underline text-black mb-2" class="flex items-center cursor-pointer text-black mb-2"
on:click={() => {
goto(`${$page.path}?submissionId=${item.id}`);
}}
> >
<img <img
alt="Student avatar" alt="Student avatar"
@@ -310,6 +329,15 @@
{`${item.tutor ? 'created by' + item.tutor.name : ''}`} {`${item.tutor ? 'created by' + item.tutor.name : ''}`}
</p> </p>
</a> </a>
<p class="text-gray-500 text-xs">
{item.submittedAt}
</p>
<!-- <div class="badge rounded-md px-2 bg-green-500 text-white">
early
</div>
<div class="badge rounded-md px-2 bg-red-600 text-white">
late
</div> -->
</div> </div>
{/each} {/each}
</div> </div>
+13
View File
@@ -0,0 +1,13 @@
export default (date) => {
const d = new Date(date);
const ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(d);
const mo = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(d);
const da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(d);
// return `${ye}-${mo}-${da} ${d.toLocaleTimeString('en-US')}`;
return new Intl.DateTimeFormat('en-US', {
dateStyle: 'full',
timeStyle: 'medium',
}).format(d);
};
+5
View File
@@ -0,0 +1,5 @@
export default (created_at, due_date) => {
return !!due_date
? !!(new Date(created_at).getTime() <= new Date(due_date).getTime())
: true;
};
+2 -1
View File
@@ -10,9 +10,10 @@ export function fetchSubmissions(course_id) {
.select( .select(
` `
id, id,
created_at,
answers:question_answer(*), answers:question_answer(*),
exercise:exercise_id( exercise:exercise_id(
id, title, id, title, due_by,
lesson:lesson_id(id, title), lesson:lesson_id(id, title),
questions:question( questions:question(
*, *,