CLASSROOMIO-T-4: Add deadline and show it was late or early
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
QUESTION_TYPES,
|
||||
} from '../../../../Question/constants';
|
||||
import { filterOutDeleted } from './functions';
|
||||
import Date from '../../../../Form/Date.svelte';
|
||||
// import EditContent from "../../../../EditContent/index.svelte";
|
||||
// import readme from "../../readme.js";
|
||||
|
||||
@@ -100,11 +101,12 @@
|
||||
/>
|
||||
<DateTime
|
||||
label="Due by"
|
||||
bind:value={$questionnaire.due_by}
|
||||
placeholder="2021-03-25"
|
||||
className="w-50"
|
||||
useTime={true}
|
||||
onChange={() => ($questionnaire.is_due_by_dirty = true)}
|
||||
value={$questionnaire.due_by}
|
||||
onInput={(e) => {
|
||||
$questionnaire.due_by = e.target.value;
|
||||
$questionnaire.is_due_by_dirty = true;
|
||||
}}
|
||||
/>
|
||||
<EditContent
|
||||
writeLabel="Description"
|
||||
|
||||
@@ -116,7 +116,22 @@
|
||||
<div
|
||||
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 class="flex items-center text-sm p-3">
|
||||
@@ -148,3 +163,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.badge {
|
||||
width: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script>
|
||||
import marked from 'marked';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { group, course } from '../../../store';
|
||||
import { questionnaire } from '../store/exercise';
|
||||
@@ -198,14 +199,23 @@
|
||||
</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>
|
||||
|
||||
<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
|
||||
onClick={handleStart}
|
||||
label="Start"
|
||||
className="my-5"
|
||||
className="my-5 float-right"
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
export let placeholder;
|
||||
export let value;
|
||||
export let className = '';
|
||||
export let onChange = () => {}; // This is to know if element is 'dirty'
|
||||
export let onInput = () => {};
|
||||
$: console.log(`value`, value);
|
||||
</script>
|
||||
|
||||
<label class="block {className}">
|
||||
<span class="text-gray-700">{label}</span>
|
||||
<input
|
||||
bind:value
|
||||
on:input={onInput}
|
||||
{placeholder}
|
||||
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"
|
||||
on:blur={onChange}
|
||||
/>
|
||||
</label>
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--main-primary-color);
|
||||
padding: 0 1.5em;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
|
||||
@@ -61,6 +61,10 @@
|
||||
fill: var(--main-primary-color);
|
||||
}
|
||||
|
||||
.prose a {
|
||||
color: var(--main-primary-color);
|
||||
}
|
||||
|
||||
.success :global(svg.carbon-icon) {
|
||||
fill: green;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
import { formatAnswers } from '../../../components/Course/function';
|
||||
import { snackbarStore } from '../../../components/Snackbar/store';
|
||||
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;
|
||||
|
||||
@@ -188,12 +191,22 @@
|
||||
const sectionById = {};
|
||||
|
||||
for (const submission of submissions) {
|
||||
const { id, exercise, course, answers, groupmember, status_id } =
|
||||
submission;
|
||||
const {
|
||||
id,
|
||||
created_at,
|
||||
exercise,
|
||||
course,
|
||||
answers,
|
||||
groupmember,
|
||||
status_id,
|
||||
} = submission;
|
||||
const isEarly = isSubmissionEarly(created_at, exercise.due_by);
|
||||
|
||||
const submissionItem = {
|
||||
id,
|
||||
statusId: status_id,
|
||||
isEarly,
|
||||
submittedAt: formatDate(created_at),
|
||||
exercise: {
|
||||
id: exercise.id,
|
||||
title: exercise.title,
|
||||
@@ -205,10 +218,11 @@
|
||||
title: exercise.lesson.title,
|
||||
},
|
||||
};
|
||||
console.log(`answers`, answers);
|
||||
|
||||
submissionIdData[id] = {
|
||||
id,
|
||||
status_id,
|
||||
isEarly,
|
||||
title: exercise.title,
|
||||
student: submissionItem.student,
|
||||
questions: exercise.questions,
|
||||
@@ -281,11 +295,16 @@
|
||||
>
|
||||
{#each items as item (item.id)}
|
||||
<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 }}
|
||||
>
|
||||
<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
|
||||
alt="Student avatar"
|
||||
@@ -310,6 +329,15 @@
|
||||
{`${item.tutor ? 'created by' + item.tutor.name : ''}`}
|
||||
</p>
|
||||
</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>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export default (created_at, due_date) => {
|
||||
return !!due_date
|
||||
? !!(new Date(created_at).getTime() <= new Date(due_date).getTime())
|
||||
: true;
|
||||
};
|
||||
@@ -10,9 +10,10 @@ export function fetchSubmissions(course_id) {
|
||||
.select(
|
||||
`
|
||||
id,
|
||||
created_at,
|
||||
answers:question_answer(*),
|
||||
exercise:exercise_id(
|
||||
id, title,
|
||||
id, title, due_by,
|
||||
lesson:lesson_id(id, title),
|
||||
questions:question(
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user