Add people + Move fetching to client side

This commit is contained in:
rotimi-best
2021-08-24 10:45:43 +03:00
parent b3e68119a7
commit 6ef33cbfd0
27 changed files with 7073 additions and 320 deletions
@@ -47,6 +47,7 @@
}
async function getExercises() {
if (!lessonId) return;
const exercisesData = await supabase
.from('exercise')
.select(`id, title, created_at`)
@@ -125,7 +126,7 @@
</div>
</Modal>
<PageBody width="w-11/12 m-auto">
<PageBody>
<slot:fragment slot="header">
<PrimaryButton
className="mr-2"
@@ -1,10 +1,11 @@
<script>
import { onMount } from 'svelte';
import CheckmarkFilled20 from 'carbon-icons-svelte/lib/CheckmarkFilled20';
import { stores, goto } from '@sapper/app';
import hotkeys from 'hotkeys-js';
import CheckmarkFilled20 from 'carbon-icons-svelte/lib/CheckmarkFilled20';
import Settings20 from 'carbon-icons-svelte/lib/Settings20';
import ChevronLeft32 from 'carbon-icons-svelte/lib/ChevronLeft32';
import ChevronRight32 from 'carbon-icons-svelte/lib/ChevronRight32';
import { stores, goto } from '@sapper/app';
import Expandable from '../../../Expandable/index.svelte';
import PageNav from '../../../PageNav/index.svelte';
import IconButton from '../../../IconButton/index.svelte';
@@ -14,6 +15,8 @@
getLectureNo,
} from '../../function';
import Settings from '../Settings/index.svelte';
import { settingsDialog } from '../Settings/store';
import { lessons } from '../Lesson/store/lessons';
import { course } from '../../store';
import { updateCourse } from '../../../../utils/services/courses';
@@ -78,32 +81,42 @@
to: getNavItemRoute($course.id, 'submissions'),
hideSortIcon: true,
},
{
label: 'Scoreboard',
to: getNavItemRoute($course.id, 'scoreboard'),
hideSortIcon: true,
},
// {
// label: 'Scoreboard',
// to: getNavItemRoute($course.id, 'scoreboard'),
// hideSortIcon: true,
// },
{
label: 'People',
to: getNavItemRoute($course.id, 'people'),
hideSortIcon: true,
},
{
label: 'Timetable',
to: getNavItemRoute($course.id, 'timetable'),
hideSortIcon: true,
},
// {
// label: 'Timetable',
// to: getNavItemRoute($course.id, 'timetable'),
// hideSortIcon: true,
// },
];
}
</script>
<Settings />
<div class="root z-10 {!show && 'hide'}">
{#if show}
<PageNav
bind:title={$course.title}
onEditComplete={handleSaveTitle}
isTitleEditable={true}
/>
paddingClass="pl-2"
>
<slot:fragment slot="widget">
<IconButton
onClick={() => ($settingsDialog.open = !$settingsDialog.open)}
>
<Settings20 class="carbon-icon" />
</IconButton>
</slot:fragment>
</PageNav>
<div>
{#each navItems as navItem}
<Expandable
@@ -0,0 +1,96 @@
<script>
import Modal from '../../../Modal/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import { ROLE } from '../../../../utils/constants/roles';
import {
addGroupMember,
fetchGroup,
} from '../../../../utils/services/courses';
import { invitationModal } from './store';
import { validateForm } from '../../../Courses/functions';
import { course, setCourseData } from '../../../Course/store';
let errors = {
emails: '',
};
function addPerson() {
const { hasError, fieldErrors, students, tutors } = validateForm({
...$invitationModal,
title: 'sfdsd',
description: 'dsfdsf',
});
errors = fieldErrors;
if (hasError) return;
let membersStack = [];
console.log(`$course`, $course);
// Create groupmemebers from group_id and add teachers and students
for (const student of students) {
membersStack.push({
email: student,
group_id: $course.group.id,
role_id: ROLE.STUDENT,
});
}
for (const tutor of tutors) {
membersStack.push({
email: tutor,
group_id: $course.group.id,
role_id: ROLE.TUTOR,
});
}
addGroupMember(membersStack).then(async (membersAdded) => {
console.log(`membersAdded`, membersAdded);
const group = await fetchGroup($course.group.id);
setCourseData(
{
...$course,
group: group.data,
},
false
);
$invitationModal.open = false;
});
}
</script>
<Modal
onClose={() => ($invitationModal.open = false)}
bind:open={$invitationModal.open}
width="w-2/5"
modalHeading="Create a Course"
>
<form on:submit|preventDefault={addPerson}>
<TextArea
label="Invite Tutors"
bind:value={$invitationModal.tutors}
rows="2"
maxRows="3"
placeholder="[email protected], [email protected]"
helperMessage="To invite people, add their emails separated by a comma"
errorMessage={errors.tutors}
className="mb-4"
/>
<TextArea
label="Invite Students"
bind:value={$invitationModal.students}
rows="2"
maxRows="3"
placeholder="[email protected], [email protected]"
helperMessage="To invite people, add their emails separated by a comma"
errorMessage={errors.students}
className="mb-4"
/>
<div class="mt-5 flex items-center">
<PrimaryButton className="px-6 py-2" label="Finish" type="submit" />
</div>
</form>
</Modal>
@@ -0,0 +1,7 @@
import { writable } from 'svelte/store';
export const invitationModal = writable({
open: false,
tutors: '',
students: '',
});
@@ -0,0 +1,13 @@
export interface Profile {
id: string;
fullname: string;
username: string;
email: string;
}
export interface Person {
id: string;
email?: string;
role_id: number;
profile?: Profile;
}
@@ -0,0 +1,81 @@
<script>
import Modal from '../../../Modal/index.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import { VARIANTS } from '../../../PrimaryButton/constants';
import { settingsDialog } from './store';
import { course } from '../../store';
import {
updateCourse,
deleteCourse,
} from '../../../../utils/services/courses';
let shouldDelete = false;
async function updateDescription() {
console.log('update');
$settingsDialog.open = false;
await updateCourse($course.id, {
description: $course.description,
});
}
async function handleDelete() {
console.log('delete');
$settingsDialog.open = false;
await deleteCourse($course.id);
}
</script>
<Modal
onClose={() => ($settingsDialog.open = false)}
bind:open={$settingsDialog.open}
width="w-96"
modalHeading="Update Course"
>
{#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.OUTLINED}
label="Yes, delete"
onClick={handleDelete}
/>
</div>
</form>
{:else}
<form on:submit|preventDefault={updateDescription}>
<TextArea
label="Short description"
bind:value={$course.description}
rows="4"
maxRows="4"
placeholder="A little description about this course"
className="mb-4"
isRequired={true}
/>
<div class="mt-5 flex items-center justify-between">
<PrimaryButton
className="px-6 py-2"
variant={VARIANTS.CONTAINED_DANGER}
label="Delete"
onClick={() => (shouldDelete = true)}
/>
<PrimaryButton className="px-6 py-2" label="Update" type="submit" />
</div>
</form>
{/if}
</Modal>
@@ -0,0 +1,5 @@
import { writable } from 'svelte/store';
export const settingsDialog = writable({
open: false,
});
+3 -2
View File
@@ -3,6 +3,7 @@
import PageNav from '../PageNav/index.svelte';
import MODES from '../../utils/constants/mode';
import PrimaryButton from '../PrimaryButton/index.svelte';
import PageBody from '../PageBody/index.svelte';
import EditContent from '../EditContent/index.svelte';
import { course } from '../Course/store';
import { updateCourse } from '../../utils/services/courses';
@@ -37,7 +38,7 @@
</svelte:fragment>
</PageNav>
<div class="px-3">
<PageBody>
{#if mode === MODES.edit}
<EditContent
writeLabel="Note"
@@ -51,4 +52,4 @@
{:else}
{@html marked($course.overview || '', { breaks: true, gfm: true })}
{/if}
</div>
</PageBody>
+11 -9
View File
@@ -26,9 +26,9 @@ export const group = writable({
students: [],
});
export async function setCourseData(data) {
export async function setCourseData(data, setLesson = true) {
if (!data || !(Object.values(data) && Object.values(data).length)) return;
console.log(`data`, data);
console.log(`setCourseData`, data);
if (data.group) {
const groupData = Object.assign(data.group, { tutors: [], students: [] });
@@ -37,7 +37,8 @@ export async function setCourseData(data) {
for (const member of groupData.members) {
if (member.role_id === ROLE.STUDENT) {
groupData.students.push(member);
} else if (member.profile) {
// } else if (member.profile) {
} else {
groupData.tutors.push({
...member,
...member.profile,
@@ -51,12 +52,13 @@ export async function setCourseData(data) {
group.set(groupData);
}
const orderedLessons = (data.lessons || []).sort(
(a, b) => new Date(a.created_at) - new Date(b.created_at)
);
// .map();
lessons.set(orderedLessons);
if (setLesson) {
const orderedLessons = (data.lessons || []).sort(
(a, b) => new Date(a.created_at) - new Date(b.created_at)
);
// .map();
lessons.set(orderedLessons);
}
delete data.lessons;
course.set(data);