CLASSROOMIO-T-146:Made the course page responsive
CLASSROOMIO-T-146:Made updates to the code following the reviews CLASSROOMIO-T-146:Made updates to the Z-Index Merge branch 'main' into CLASSROOMIO-T-146 Merge branch 'main' into CLASSROOMIO-T-146 CLASSROOMIO-T-146:Made the course page responsive CLASSROOMIO-T-146:working on the course page responsiveness Merge branch 'main' into CLASSROOMIO-T-145 CLASSROOMIO-T-146:Making the course page responsive CLASSROOMIO-T-145: All done and ready CLASSROOMIO-T-145: All done and ready CLASSROOMIO-T-145: Fixed the Z-index issue Merge branch 'main' into CLASSROOMIO-T-145 CLASSROOMIO-T-145: Finished implementing the responsive design for the Main dashboard and LMS dashboard Merge branch 'main' into CLASSROOMIO-T-145 CLASSROOMIO-T-144:Updating the dashboard responsiveness ooth for LMS and the Main dashboard CLASSROOMIO-T-144:Updated the dashboard responsiveness ooth for LMS and the Main dashboard Merge branch 'main' into CLASSROOMIO-T-145 CLASSROOMIO-T-145:Made the LMS dashboard responsive Co-authored-by: Ifeanyi Nwosu <ifeanyi@digdippa.com> Merge-request: CLASSROOMIO-MR-73 Merged-by: Best Admin <best@digdippa.com>
This commit is contained in:
@@ -14,6 +14,11 @@ html {
|
|||||||
#calendar .grid {
|
#calendar .grid {
|
||||||
--sc-theme-calendar-colors-background-highlight: var(--main-primary-color);
|
--sc-theme-calendar-colors-background-highlight: var(--main-primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html .dark {
|
||||||
|
--scrollbarBG: #1f2937;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
|
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
|
||||||
|
|||||||
@@ -6,12 +6,15 @@
|
|||||||
import SendAlt from 'carbon-icons-svelte/lib/SendAlt.svelte';
|
import SendAlt from 'carbon-icons-svelte/lib/SendAlt.svelte';
|
||||||
import ChartPie from 'carbon-icons-svelte/lib/ChartPie.svelte';
|
import ChartPie from 'carbon-icons-svelte/lib/ChartPie.svelte';
|
||||||
import IconButton from '$lib/components/IconButton/index.svelte';
|
import IconButton from '$lib/components/IconButton/index.svelte';
|
||||||
|
import Settings from 'carbon-icons-svelte/lib/Settings.svelte';
|
||||||
|
import { apps } from './store';
|
||||||
|
|
||||||
import QandA from './components/QandA/index.svelte';
|
import QandA from './components/QandA/index.svelte';
|
||||||
import LiveChat from './components/LiveChat/index.svelte';
|
import LiveChat from './components/LiveChat/index.svelte';
|
||||||
import Notes from './components/Notes/index.svelte';
|
import Notes from './components/Notes/index.svelte';
|
||||||
import Poll from './components/Poll/index.svelte';
|
import Poll from './components/Poll/index.svelte';
|
||||||
import APPS_CONSTANTS from './constants';
|
import APPS_CONSTANTS from './constants';
|
||||||
|
import { OverflowMenu, OverflowMenuItem } from 'carbon-components-svelte';
|
||||||
|
|
||||||
let selectedApp;
|
let selectedApp;
|
||||||
|
|
||||||
@@ -48,8 +51,21 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class={`root ${$apps.open ? 'open dark:bg-slate-800' : 'close dark:bg-slate-800'}`}>
|
||||||
<div class="apps">
|
<div class={`apps`}>
|
||||||
|
<div class="lg:hidden">
|
||||||
|
<IconButton
|
||||||
|
buttonClassName="lg:hidden"
|
||||||
|
toolTipProps={{ title: 'Settings', hotkeys: ['A', '0'] }}
|
||||||
|
onClick={() => {
|
||||||
|
handleAppClick;
|
||||||
|
$apps.dropdown = !$apps.dropdown;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Settings size={24} class="carbon-icon dark:text-white lg:hidden" />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
toolTipProps={{ title: 'Live Chat', hotkeys: ['A', '1'] }}
|
toolTipProps={{ title: 'Live Chat', hotkeys: ['A', '1'] }}
|
||||||
value={APPS_CONSTANTS.APPS.LIVE_CHAT}
|
value={APPS_CONSTANTS.APPS.LIVE_CHAT}
|
||||||
@@ -104,7 +120,7 @@
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.root {
|
.root {
|
||||||
height: 93vh;
|
height: calc(100vh - 48px);
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
border-left: 1px solid var(--border-color);
|
border-left: 1px solid var(--border-color);
|
||||||
@@ -129,4 +145,25 @@
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
.root {
|
||||||
|
position: absolute;
|
||||||
|
height: calc(100vh - 109px);
|
||||||
|
top: 109px;
|
||||||
|
right: 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
.open {
|
||||||
|
position: absolute;
|
||||||
|
transform: translateX(0);
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
transform: translateX(100%);
|
||||||
|
display: none;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export const apps = writable({
|
||||||
|
open: false,
|
||||||
|
dropdown: false
|
||||||
|
});
|
||||||
@@ -45,8 +45,8 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<main class="md:-ml-4 md:-mr-4 px-2">
|
<main class="md:-ml-4 md:-mr-4 px-2">
|
||||||
<div class="flex-1 flex flex-col md:flex-row justify-between gap-3 w-full mb-3 h-4/5">
|
<div class="flex-1 flex flex-col lg:flex-row justify-between gap-3 w-full mb-3 h-4/5">
|
||||||
<section class="w-full md:w-2/5 h-full">
|
<section class="w-full lg:w-2/5 h-full">
|
||||||
<strong class="my-2 text-base font-semibold text-black dark:text-gray-100"
|
<strong class="my-2 text-base font-semibold text-black dark:text-gray-100"
|
||||||
>Certificate settings</strong
|
>Certificate settings</strong
|
||||||
>
|
>
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section
|
<section
|
||||||
class="bg-gray-100 dark:bg-gray-700 flex justify-center items-center rounded-md w-full md:w-3/5"
|
class="bg-gray-100 dark:bg-gray-700 flex justify-center items-center rounded-md w-full lg:w-3/5"
|
||||||
>
|
>
|
||||||
<div class="certificate-container flex justify-center items-center h-5/6">
|
<div class="certificate-container flex justify-center items-center h-5/6">
|
||||||
{#if $course.certificate_theme === 'professional'}
|
{#if $course.certificate_theme === 'professional'}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
<Modal
|
<Modal
|
||||||
onClose={() => (openModal = false)}
|
onClose={() => (openModal = false)}
|
||||||
bind:open={openModal}
|
bind:open={openModal}
|
||||||
width="w-[60%]"
|
width="w-[80%] md:w-[60%]"
|
||||||
containerClass="overflow-hidden"
|
containerClass="overflow-hidden"
|
||||||
modalHeading="Add New Lesson"
|
modalHeading="Add New Lesson"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -165,8 +165,8 @@
|
|||||||
<p class="dark:text-white mt-4 text-sm">Created Jul 3, 2021</p>
|
<p class="dark:text-white mt-4 text-sm">Created Jul 3, 2021</p>
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
<Box className="mt-3">
|
<Box className="mt-3 text-center">
|
||||||
<div class="flex justify-between flex-col items-center w-96">
|
<div class="flex justify-between flex-col items-center w-[80%] md:w-96">
|
||||||
<img src="/images/empty-exercise-icon.svg" alt="Exercise" class="my-2.5 mx-auto" />
|
<img src="/images/empty-exercise-icon.svg" alt="Exercise" class="my-2.5 mx-auto" />
|
||||||
<h2 class="text-xl my-1.5 font-normal">No exercises added for this lesson</h2>
|
<h2 class="text-xl my-1.5 font-normal">No exercises added for this lesson</h2>
|
||||||
<p class="text-sm text-center text-slate-500">
|
<p class="text-sm text-center text-slate-500">
|
||||||
|
|||||||
@@ -11,13 +11,15 @@
|
|||||||
const onChange = (tab) => () => (currentTab = tab);
|
const onChange = (tab) => () => (currentTab = tab);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="w-full h-full flex flex-row items-start gap-3">
|
<section class="w-full h-full flex flex-col md:flex-row items-start gap-3">
|
||||||
<div class="flex-1 flex-col">
|
<div class="flex flex-row md:flex-col gap-2 items-center">
|
||||||
<p class="text-sm font-normal text-start text-[#4F4B4B] dark:text-[#b0a9a9] mb-3">Add By</p>
|
<p class="text-sm font-normal text-start text-[#4F4B4B] dark:text-[#b0a9a9] mb-3 w-full">
|
||||||
|
Add By
|
||||||
|
</p>
|
||||||
{#each tabs as item (item.value)}
|
{#each tabs as item (item.value)}
|
||||||
<button
|
<button
|
||||||
on:click={onChange(item.value)}
|
on:click={onChange(item.value)}
|
||||||
class={`w-full px-4 py-3 my-5 border ${
|
class={`w-full px-4 py-3 my-1 border ${
|
||||||
currentTab === item.value
|
currentTab === item.value
|
||||||
? 'border border-[#0233BD] bg-[#F5F8FE] dark:text-black'
|
? 'border border-[#0233BD] bg-[#F5F8FE] dark:text-black'
|
||||||
: 'border border-gray-200'
|
: 'border border-gray-200'
|
||||||
|
|||||||
@@ -197,13 +197,13 @@
|
|||||||
<Modal
|
<Modal
|
||||||
{onClose}
|
{onClose}
|
||||||
bind:open={$uploadCourseVideoStore.isModalOpen}
|
bind:open={$uploadCourseVideoStore.isModalOpen}
|
||||||
width="w-4/5 h-[566px]"
|
width="w-4/5 w-[90%] h-[80%] md:h-[566px]"
|
||||||
modalHeading="Add a Video"
|
modalHeading="Add a Video"
|
||||||
>
|
>
|
||||||
<VideoUploader {lessonId} />
|
<VideoUploader {lessonId} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<h1 class="text-4xl mt-0">
|
<h1 class="text-4xl mt-0 capitalize">
|
||||||
{lessonTitle}
|
{lessonTitle}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
</article>
|
</article>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<Box>
|
<Box className="text-center">
|
||||||
<img src="/no-video.svg" alt="Video not found" />
|
<img src="/no-video.svg" alt="Video not found" />
|
||||||
<h3 class="text-xl font-normal dark:text-white py-2">
|
<h3 class="text-xl font-normal dark:text-white py-2">
|
||||||
No note, video or slide added for this lesson yet
|
No note, video or slide added for this lesson yet
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
import { updateCourse } from '$lib/utils/services/courses';
|
import { updateCourse } from '$lib/utils/services/courses';
|
||||||
import { NavClasses } from '$lib/utils/constants/reusableClass';
|
import { NavClasses } from '$lib/utils/constants/reusableClass';
|
||||||
import { isMobile } from '$lib/utils/store/useMobile';
|
import { isMobile } from '$lib/utils/store/useMobile';
|
||||||
|
import { menu } from '$lib/components/Org/store';
|
||||||
|
|
||||||
// export let lessonId;
|
// export let lessonId;
|
||||||
export let path;
|
export let path;
|
||||||
@@ -32,12 +33,14 @@
|
|||||||
let show = null;
|
let show = null;
|
||||||
let isLessonActive = false;
|
let isLessonActive = false;
|
||||||
|
|
||||||
|
const toggleSidebar = () => {
|
||||||
|
$menu.hidden = !$menu.hidden;
|
||||||
|
};
|
||||||
|
|
||||||
function handleMainGroupClick(href) {
|
function handleMainGroupClick(href) {
|
||||||
return () => {
|
return () => {
|
||||||
if ($isMobile) {
|
|
||||||
setTimeout(() => (show = false), 500);
|
|
||||||
}
|
|
||||||
goto(href);
|
goto(href);
|
||||||
|
toggleSidebar();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,145 +149,66 @@
|
|||||||
|
|
||||||
<Settings />
|
<Settings />
|
||||||
|
|
||||||
<div class="root z-10 {!show && 'hide'} {$isMobile ? 'fixed shadow-xl' : 'sticky'}">
|
<aside
|
||||||
{#if show}
|
class={`${
|
||||||
<div class="relative h-full dark:bg-gray-800">
|
$menu.hidden
|
||||||
<!-- <PageNav title="Back to courses" paddingClass="pl-2" titleSize="text-md">
|
? '-translate-x-[100%] absolute md:translate-x-0 md:relative z-[40]'
|
||||||
<slot:fragment slot="image">
|
: 'translate-x-0 absolute md:relative z-[40]'
|
||||||
<Avatar src={$course.logo} />
|
} transition w-[250px] min-w-[250px] bg-gray-100 dark:bg-gray-800 h-[calc(100vh-48px)] border border-l-0 border-t-0 border-b-0 border-r-1`}
|
||||||
<IconButton
|
>
|
||||||
value="toggle"
|
<div class="h-full flex flex-col">
|
||||||
onClick={() => goto(`${$currentOrgPath}/courses`)}
|
<ul class="my-5">
|
||||||
size="small"
|
{#each navItems as navItem}
|
||||||
contained={true}
|
{#if !navItem.show || (typeof navItem.show === 'function' && navItem.show())}
|
||||||
|
<NavExpandable
|
||||||
|
label={navItem.label}
|
||||||
|
handleClick={handleMainGroupClick(navItem.to)}
|
||||||
|
isGroupActive={(path || $page.url.pathname) === navItem.to}
|
||||||
|
isExpanded={isLessonActive}
|
||||||
|
total={navItem.isLecture ? ($lessons || []).length : 0}
|
||||||
>
|
>
|
||||||
<ArrowLeftIcon size={20} class="carbon-icon dark:text-white" />
|
{#if navItem.isLecture}
|
||||||
</IconButton>
|
{#each $lessons as item, index}
|
||||||
</slot:fragment>
|
<a
|
||||||
<slot:fragment slot="widget">
|
class="pl-7 w-[95%] text-[0.80rem] mb-1 text-black dark:text-white {isStudent &&
|
||||||
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
!item.is_unlocked
|
||||||
<IconButton onClick={() => ($settingsDialog.open = !$settingsDialog.open)}>
|
? 'cursor-not-allowed'
|
||||||
<SettingsIcon size={20} class="carbon-icon dark:text-white" />
|
: ''}"
|
||||||
</IconButton>
|
href={isStudent && !item.is_unlocked
|
||||||
</RoleBasedSecurity>
|
? $page.url.pathname
|
||||||
</slot:fragment>
|
: getLessonsRoute($course.id, item.id)}
|
||||||
</PageNav> -->
|
on:click={toggleSidebar}
|
||||||
<div class="h-full py-3 overflow-y-auto">
|
aria-disabled={!item.is_unlocked}
|
||||||
{#each navItems as navItem}
|
>
|
||||||
{#if !navItem.show || (typeof navItem.show === 'function' && navItem.show())}
|
<div
|
||||||
<NavExpandable
|
class="flex items-center py-3 px-4 {NavClasses.item} {(
|
||||||
label={navItem.label}
|
path || $page.url.pathname
|
||||||
handleClick={handleMainGroupClick(navItem.to)}
|
).includes(item.id) && NavClasses.active}"
|
||||||
isGroupActive={(path || $page.url.pathname) === navItem.to}
|
|
||||||
isExpanded={isLessonActive}
|
|
||||||
total={navItem.isLecture ? ($lessons || []).length : 0}
|
|
||||||
>
|
|
||||||
{#if navItem.isLecture}
|
|
||||||
{#each $lessons as item, index}
|
|
||||||
<a
|
|
||||||
class="pl-7 w-[95%] text-[0.80rem] mb-1 text-black dark:text-white {isStudent &&
|
|
||||||
!item.is_unlocked
|
|
||||||
? 'cursor-not-allowed'
|
|
||||||
: ''}"
|
|
||||||
href={isStudent && !item.is_unlocked
|
|
||||||
? $page.url.pathname
|
|
||||||
: getLessonsRoute($course.id, item.id)}
|
|
||||||
on:click={() => {
|
|
||||||
if ($isMobile) {
|
|
||||||
setTimeout(() => (show = false), 500);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
aria-disabled={!item.is_unlocked}
|
|
||||||
>
|
>
|
||||||
<div
|
<TextChip
|
||||||
class="flex items-center py-3 px-4 {NavClasses.item} {(
|
value={getLectureNo(index + 1)}
|
||||||
path || $page.url.pathname
|
className="bg-primary-200 text-primary-600 text-xs mr-2"
|
||||||
).includes(item.id) && NavClasses.active}"
|
size="sm"
|
||||||
>
|
shape="rounded-full"
|
||||||
<TextChip
|
/>
|
||||||
value={getLectureNo(index + 1)}
|
<span>{item.title}</span>
|
||||||
className="bg-primary-200 text-primary-600 text-xs mr-2"
|
<span class="grow" />
|
||||||
size="sm"
|
{#if !item.is_unlocked}
|
||||||
shape="rounded-full"
|
<span class="text-md ml-2" title="This lesson is locked.">
|
||||||
/>
|
<LockedIcon class="carbon-icon dark:text-white" />
|
||||||
<span>{item.title}</span>
|
</span>
|
||||||
<span class="grow" />
|
{:else if item.is_complete}
|
||||||
{#if !item.is_unlocked}
|
<span class="ml-2" title="You have completed this lesson">
|
||||||
<span class="text-md ml-2" title="This lesson is locked.">
|
<CheckmarkFilled class="carbon-icon dark:text-white" />
|
||||||
<LockedIcon class="carbon-icon dark:text-white" />
|
</span>
|
||||||
</span>
|
{/if}
|
||||||
{:else if item.is_complete}
|
</div>
|
||||||
<span class="ml-2" title="You have completed this lesson">
|
</a>
|
||||||
<CheckmarkFilled class="carbon-icon dark:text-white" />
|
{/each}
|
||||||
</span>
|
{/if}
|
||||||
{/if}
|
</NavExpandable>
|
||||||
</div>
|
{/if}
|
||||||
</a>
|
{/each}
|
||||||
{/each}
|
</ul>
|
||||||
{/if}
|
|
||||||
</NavExpandable>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div class="toggler rounded-full shadow-lg absolute bottom-0">
|
|
||||||
<IconButton
|
|
||||||
value="toggle"
|
|
||||||
onClick={() => (show = !show)}
|
|
||||||
size={$isMobile ? 'large' : 'small'}
|
|
||||||
color="text-black"
|
|
||||||
toolTipProps={$isMobile
|
|
||||||
? {}
|
|
||||||
: {
|
|
||||||
title: 'Toggle sidebar',
|
|
||||||
hotkeys: ['B'],
|
|
||||||
direction: 'right'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{#if show}
|
|
||||||
<ChevronLeftIcon size={16} />
|
|
||||||
{:else}
|
|
||||||
<ChevronRightIcon size={16} />
|
|
||||||
{/if}
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</aside>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.root {
|
|
||||||
height: calc(100vh - 48px);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-width: 360px;
|
|
||||||
max-width: 360px;
|
|
||||||
top: 0;
|
|
||||||
border-right: 1px solid var(--border-color);
|
|
||||||
background-color: rgb(250, 251, 252);
|
|
||||||
|
|
||||||
&.hide {
|
|
||||||
min-width: 15px;
|
|
||||||
max-width: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.footer {
|
|
||||||
border-top: 1px solid var(--border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggler {
|
|
||||||
right: -15px;
|
|
||||||
z-index: 10;
|
|
||||||
border: 1px solid var(--border-color);
|
|
||||||
top: 50px;
|
|
||||||
height: fit-content;
|
|
||||||
background: var(--border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 760px) {
|
|
||||||
.root {
|
|
||||||
width: 98%;
|
|
||||||
min-width: unset;
|
|
||||||
max-width: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -145,7 +145,7 @@
|
|||||||
<Modal
|
<Modal
|
||||||
onClose={resetForm}
|
onClose={resetForm}
|
||||||
bind:open={$invitationModal.open}
|
bind:open={$invitationModal.open}
|
||||||
width="w-2/5"
|
width="w-4/5 md:w-2/5"
|
||||||
maxWidth="max-w-lg"
|
maxWidth="max-w-lg"
|
||||||
modalHeading="Invite people"
|
modalHeading="Invite people"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -16,9 +16,7 @@
|
|||||||
export let isFetching = false;
|
export let isFetching = false;
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
const user = $group.people.find(
|
const user = $group.people.find((person) => person.profile_id === $profile.id);
|
||||||
(person) => person.profile_id === $profile.id
|
|
||||||
);
|
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
isStudent = user.role_id === 3;
|
isStudent = user.role_id === 3;
|
||||||
@@ -58,6 +56,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.rightBar.isMobile {
|
.rightBar.isMobile {
|
||||||
margin-left: 10px;
|
/* margin-left: 10px; */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -7,36 +7,12 @@
|
|||||||
export let show = true;
|
export let show = true;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section
|
<section class="root z-10">
|
||||||
class="root z-10 {!show && 'hide'} {$isMobile ? 'fixed shadow-xl' : 'sticky'}"
|
|
||||||
>
|
|
||||||
{#if show}
|
{#if show}
|
||||||
<div class="relative h-full bg-white dark:bg-gray-800">
|
<div class="relative h-full bg-white dark:bg-gray-800">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="toggler rounded-full shadow-lg absolute bottom-0">
|
|
||||||
<IconButton
|
|
||||||
value="toggle"
|
|
||||||
onClick={() => (show = !show)}
|
|
||||||
size={$isMobile ? 'large' : 'small'}
|
|
||||||
color="text-black"
|
|
||||||
toolTipProps={$isMobile
|
|
||||||
? {}
|
|
||||||
: {
|
|
||||||
title: 'Toggle editor',
|
|
||||||
hotkeys: ['B'],
|
|
||||||
direction: 'right',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{#if show}
|
|
||||||
<ChevronLeftIcon size={16} />
|
|
||||||
{:else}
|
|
||||||
<ChevronRightIcon size={16} />
|
|
||||||
{/if}
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@@ -50,11 +26,6 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
border-right: 1px solid var(--border-color);
|
border-right: 1px solid var(--border-color);
|
||||||
background-color: rgb(250, 251, 252);
|
background-color: rgb(250, 251, 252);
|
||||||
|
|
||||||
&.hide {
|
|
||||||
min-width: 15px;
|
|
||||||
max-width: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggler {
|
.toggler {
|
||||||
@@ -67,10 +38,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 760px) {
|
@media (max-width: 760px) {
|
||||||
.root {
|
|
||||||
width: 98%;
|
|
||||||
min-width: unset;
|
|
||||||
max-width: unset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -18,13 +18,16 @@
|
|||||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||||
import { updateCourse } from '$lib/utils/services/courses';
|
import { updateCourse } from '$lib/utils/services/courses';
|
||||||
import generateSlug from '$lib/utils/functions/generateSlug';
|
import generateSlug from '$lib/utils/functions/generateSlug';
|
||||||
|
import ChevronLeftIcon from 'carbon-icons-svelte/lib/ChevronLeft.svelte';
|
||||||
|
|
||||||
|
import { isMobile } from '$lib/utils/store/useMobile';
|
||||||
|
|
||||||
export let course;
|
export let course;
|
||||||
export let courseId;
|
export let courseId;
|
||||||
|
|
||||||
let borderBottomGrey = 'border-r-0 border-b border-l-0 border-gray-300';
|
let borderBottomGrey = 'border-r-0 border-b border-l-0 border-gray-300';
|
||||||
let loading = false;
|
let loading = false;
|
||||||
|
let show = false;
|
||||||
const sections = [
|
const sections = [
|
||||||
{
|
{
|
||||||
key: 1,
|
key: 1,
|
||||||
@@ -115,69 +118,112 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Container show={true}>
|
<aside
|
||||||
<!-- Publish Header Section -->
|
class={`${
|
||||||
{#if !selectedSection}
|
show ? '-translate-x-[100%] fixed z-[9999]' : 'translate-x-0 fixed z-[9999]'
|
||||||
<div class="flex justify-between items-center px-2 w-full">
|
} left-0 transition w-[280px] min-w-[280px] bg-gray-100 dark:bg-gray-800 h-full border border-l-0 border-t-0 border-b-0 border-r-1`}
|
||||||
<CloseButton onClick={handleClose} />
|
>
|
||||||
<div class="flex items-center">
|
<div class="toggler rounded-full shadow-lg absolute">
|
||||||
<PrimaryButton
|
<IconButton
|
||||||
label="Save"
|
value="toggle"
|
||||||
type="button"
|
onClick={() => (show = !show)}
|
||||||
className="mr-1"
|
size={$isMobile ? 'large' : 'small'}
|
||||||
variant={VARIANTS.OUTLINED}
|
color="text-black"
|
||||||
onClick={handleSave}
|
toolTipProps={$isMobile
|
||||||
isLoading={loading}
|
? {}
|
||||||
/>
|
: {
|
||||||
<PrimaryButton label="Publish" type="button" onClick={handlePublish} isDisabled={loading} />
|
title: 'Toggle editor',
|
||||||
<IconButton onClick={handlePreview} disabled={loading || !course.slug}>
|
direction: 'right'
|
||||||
<ArrowUpRightIcon size={24} class="carbon-icon dark:text-white" title="Preview" />
|
}}
|
||||||
</IconButton>
|
>
|
||||||
</div>
|
{#if show}
|
||||||
</div>
|
<ChevronRightIcon size={16} />
|
||||||
<div class="flex justify-between items-center px-2 w-full mb-2">
|
{:else}
|
||||||
<h3 class="dark:text-white">Page Builder</h3>
|
<ChevronLeftIcon size={16} />
|
||||||
</div>
|
|
||||||
{#each sections as section}
|
|
||||||
<button
|
|
||||||
class="w-full flex items-center justify-between px-2 py-3 border border-b-0 border-gray-300"
|
|
||||||
on:click={handleSectionSelect(section.key)}
|
|
||||||
>
|
|
||||||
<p class="dark:text-white mr-2">{section.title} section</p>
|
|
||||||
<ChevronRightIcon size={24} class="carbon-class" />
|
|
||||||
</button>
|
|
||||||
{/each}
|
|
||||||
{:else}
|
|
||||||
<!-- Title -->
|
|
||||||
<div class="flex items-center {borderBottomGrey} w-full">
|
|
||||||
<IconButton onClick={handleClose}>
|
|
||||||
<ArrowLeftIcon size={24} class="carbon-icon dark:text-white" title="Go back" />
|
|
||||||
</IconButton>
|
|
||||||
<h3 class="dark:text-white">{selectedSection.title}</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="title-content p-2 overflow-y-auto">
|
|
||||||
{#if selectedSection.key === 1}
|
|
||||||
<HeaderForm bind:course />
|
|
||||||
{:else if selectedSection.key === 2}
|
|
||||||
<RequirementForm bind:course />
|
|
||||||
{:else if selectedSection.key === 3}
|
|
||||||
<DescriptionForm bind:course />
|
|
||||||
{:else if selectedSection.key === 4}
|
|
||||||
<GoalsForm bind:course />
|
|
||||||
{:else if selectedSection.key === 5}
|
|
||||||
<ReviewsForm bind:course />
|
|
||||||
{:else if selectedSection.key === 6}
|
|
||||||
<InstructorForm bind:course />
|
|
||||||
{:else if selectedSection.key === 7}
|
|
||||||
<PricingForm bind:course />
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</IconButton>
|
||||||
{/if}
|
</div>
|
||||||
</Container>
|
<div class="h-full flex flex-col">
|
||||||
|
{#if !selectedSection}
|
||||||
|
<div class="flex justify-between items-center px-2 w-full">
|
||||||
|
<CloseButton onClick={handleClose} />
|
||||||
|
<div class="flex items-center">
|
||||||
|
<PrimaryButton
|
||||||
|
label="Save"
|
||||||
|
type="button"
|
||||||
|
className="mr-1"
|
||||||
|
variant={VARIANTS.OUTLINED}
|
||||||
|
onClick={handleSave}
|
||||||
|
isLoading={loading}
|
||||||
|
/>
|
||||||
|
<PrimaryButton
|
||||||
|
label="Publish"
|
||||||
|
type="button"
|
||||||
|
onClick={handlePublish}
|
||||||
|
isDisabled={loading}
|
||||||
|
/>
|
||||||
|
<IconButton onClick={handlePreview} disabled={loading || !course.slug}>
|
||||||
|
<ArrowUpRightIcon size={24} class="carbon-icon dark:text-white" title="Preview" />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between items-center px-2 w-full mb-2">
|
||||||
|
<h3 class="dark:text-white">Page Builder</h3>
|
||||||
|
</div>
|
||||||
|
{#each sections as section}
|
||||||
|
<button
|
||||||
|
class="w-full flex items-center justify-between px-2 py-3 border border-b-0 border-gray-300"
|
||||||
|
on:click={handleSectionSelect(section.key)}
|
||||||
|
>
|
||||||
|
<p class="dark:text-white mr-2">{section.title} section</p>
|
||||||
|
<ChevronRightIcon size={24} class="carbon-class" />
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
{:else}
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="flex items-center {borderBottomGrey} w-full">
|
||||||
|
<IconButton onClick={handleClose}>
|
||||||
|
<ArrowLeftIcon size={24} class="carbon-icon dark:text-white" title="Go back" />
|
||||||
|
</IconButton>
|
||||||
|
<h3 class="dark:text-white">{selectedSection.title}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="title-content p-2 overflow-y-auto">
|
||||||
|
{#if selectedSection.key === 1}
|
||||||
|
<HeaderForm bind:course />
|
||||||
|
{:else if selectedSection.key === 2}
|
||||||
|
<RequirementForm bind:course />
|
||||||
|
{:else if selectedSection.key === 3}
|
||||||
|
<DescriptionForm bind:course />
|
||||||
|
{:else if selectedSection.key === 4}
|
||||||
|
<GoalsForm bind:course />
|
||||||
|
{:else if selectedSection.key === 5}
|
||||||
|
<ReviewsForm bind:course />
|
||||||
|
{:else if selectedSection.key === 6}
|
||||||
|
<InstructorForm bind:course />
|
||||||
|
{:else if selectedSection.key === 7}
|
||||||
|
<PricingForm bind:course />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.title-content {
|
.title-content {
|
||||||
height: 90%;
|
height: 90%;
|
||||||
}
|
}
|
||||||
|
.toggler {
|
||||||
|
right: -15px;
|
||||||
|
z-index: 10;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
top: 50px;
|
||||||
|
height: fit-content;
|
||||||
|
background: var(--border-color);
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
.toggler {
|
||||||
|
right: -25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Pricing Details -->
|
<!-- Pricing Details -->
|
||||||
<aside class="{className} price-container md:sticky md:top-0 md:shadow-2xl md:rounded-lg m-h-fit">
|
<aside class="{className} price-container lg:sticky lg:top-0 lg:shadow-2xl lg:rounded-lg m-h-fit">
|
||||||
<div class="p-10">
|
<div class="p-10">
|
||||||
<!-- Pricing -->
|
<!-- Pricing -->
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
@@ -120,9 +120,9 @@
|
|||||||
height: fit-content;
|
height: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media screen and (min-width: 768px) and (max-width: 1024px) {
|
||||||
.price-container {
|
.price-container {
|
||||||
width: 100%;
|
width: 405px;
|
||||||
min-width: unset;
|
min-width: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,12 +164,14 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<PricingSection className="md:hidden" {courseData} />
|
<!-- <PricingSection className="md:hidden" {courseData} /> -->
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
<div class="bg-white dark:bg-gray-800 w-full">
|
<div class="bg-white dark:bg-gray-800 w-full">
|
||||||
<div class="py-8 lg:w-10/12 w-full m-2 lg:m-auto flex justify-between">
|
<div
|
||||||
|
class="py-8 lg:w-11/12 w-full m-2 lg:m-auto flex flex-col-reverse lg:flex-row items-center lg:items-start justify-between"
|
||||||
|
>
|
||||||
<!-- Course Details -->
|
<!-- Course Details -->
|
||||||
<div class="course-content w-full p-3 md:w-9/12 md:mr-14">
|
<div class="course-content w-full p-3 lg:w-10/12 lg:mr-14">
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
<nav class="flex items-center border-b border-gray-300 pb-3">
|
<nav class="flex items-center border-b border-gray-300 pb-3">
|
||||||
{#each NAV_ITEMS as navItem}
|
{#each NAV_ITEMS as navItem}
|
||||||
@@ -416,7 +418,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Pricing Details -->
|
<!-- Pricing Details -->
|
||||||
<PricingSection className="hidden md:block" {courseData} />
|
<PricingSection {courseData} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -464,7 +466,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.course-content {
|
.course-content {
|
||||||
max-width: 608px;
|
max-width: 800px;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full flex flex-col">
|
<div class="w-full flex flex-col">
|
||||||
<div class="flex items-center border-b-2 w-full">
|
<div class="flex items-center border-b-2 w-full overflow-x-auto">
|
||||||
{#each tabs as tab}
|
{#each tabs as tab}
|
||||||
{#if !tab.icon && !tab.badgeValue}
|
{#if !tab.icon && !tab.badgeValue}
|
||||||
<button
|
<button
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
: 'dark:bg-gray-500 dark:text-white'} dark:bg-transparent font-semibold focus:outline-none w-24 text-left py-3 mr-10"
|
: 'dark:bg-gray-500 dark:text-white'} dark:bg-transparent font-semibold focus:outline-none w-24 text-left py-3 mr-10"
|
||||||
on:click={onChange(tab.value)}
|
on:click={onChange(tab.value)}
|
||||||
>
|
>
|
||||||
<div class="grid grid-cols-4 gap-3 items-center">
|
<div class="grid grid-cols-5 md:grid-cols-4 gap-5 md:gap-3 items-center">
|
||||||
{#if tab.icon}
|
{#if tab.icon}
|
||||||
<svelte:component this={tab.icon} />
|
<svelte:component this={tab.icon} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -315,14 +315,14 @@
|
|||||||
{#if !isQuizPage($page.url.pathname)}
|
{#if !isQuizPage($page.url.pathname)}
|
||||||
<OrgSideBar />
|
<OrgSideBar />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="org-slot w-full bg-white dark:bg-gray-800">
|
<div class="org-slot bg-white dark:bg-gray-800 w-full">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if isLMSPage($page.url.pathname)}
|
{:else if isLMSPage($page.url.pathname)}
|
||||||
<div class="org-root w-full flex items-center justify-between">
|
<div class="org-root w-full flex items-center justify-between">
|
||||||
<LMSSideBar />
|
<LMSSideBar />
|
||||||
<div class="org-slot w-full bg-white dark:bg-gray-800">
|
<div class="org-slot bg-white dark:bg-gray-800 w-full">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -138,77 +138,80 @@
|
|||||||
|
|
||||||
<CourseContainer bind:isStudent>
|
<CourseContainer bind:isStudent>
|
||||||
<PageNav title="Attendance" />
|
<PageNav title="Attendance" />
|
||||||
|
<PageBody width="w-full max-w-6xl md:w-11/12">
|
||||||
<section class="mx-9 my-5">
|
<section class="flex items-center mx-2 lg:mx-9 my-5">
|
||||||
<div class="flex flex-row items-center justify-between">
|
<div
|
||||||
<div class="flex">
|
class="flex flex-col lg:flex-row items-start gap-2 lg:items-center justify-between w-full"
|
||||||
<p class="flex items-center mr-5">
|
>
|
||||||
<Checkbox checked disabled /> Present
|
<div class="flex">
|
||||||
</p>
|
<p class="flex items-center mr-5">
|
||||||
<p class="flex items-center">
|
<Checkbox checked disabled /> Present
|
||||||
<Checkbox disabled /> Absent
|
</p>
|
||||||
</p>
|
<p class="flex items-center">
|
||||||
|
<Checkbox disabled /> Absent
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Search
|
||||||
|
class="dark:text-slate-950"
|
||||||
|
placeholder="Search students"
|
||||||
|
bind:value={searchValue}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</section>
|
||||||
<Search
|
|
||||||
class="dark:text-slate-950"
|
|
||||||
placeholder="Search students"
|
|
||||||
bind:value={searchValue}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="my-5 mx-9">
|
<section class="my-5 mx-2 lg:mx-9">
|
||||||
<StructuredList class="m-0">
|
<StructuredList class="m-0 relative">
|
||||||
<!-- Moved the lesson headers outside the students loop -->
|
<!-- Moved the lesson headers outside the students loop -->
|
||||||
<StructuredListHead class="bg-primary-100">
|
<StructuredListHead class="bg-primary-100">
|
||||||
<StructuredListRow head class="mx-7">
|
<StructuredListRow head class="mx-7">
|
||||||
<StructuredListCell head class="text-primary-600 py-3">Student</StructuredListCell>
|
<StructuredListCell head class="text-primary-600 py-3">Student</StructuredListCell>
|
||||||
{#each $lessons as lesson, index}
|
{#each $lessons as lesson, index}
|
||||||
<StructuredListCell head class="text-primary-600 py-3"
|
<StructuredListCell head class="text-primary-600 py-3"
|
||||||
>Lesson 0{getLectureNo(index + 1)}</StructuredListCell
|
>Lesson 0{getLectureNo(index + 1)}</StructuredListCell
|
||||||
>
|
>
|
||||||
{/each}
|
|
||||||
</StructuredListRow>
|
|
||||||
</StructuredListHead>
|
|
||||||
|
|
||||||
{#each searchStudents(searchValue) as student}
|
|
||||||
<StructuredListBody>
|
|
||||||
<StructuredListRow>
|
|
||||||
<StructuredListCell>
|
|
||||||
<div class="w-1/4 flex items-center">
|
|
||||||
<p class="dark:text-white font-semibold">
|
|
||||||
{student.profile.fullname}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</StructuredListCell>
|
|
||||||
{#each $lessons as lesson}
|
|
||||||
<StructuredListCell class="">
|
|
||||||
<Checkbox
|
|
||||||
class={isStudent && 'cursor-not-allowed'}
|
|
||||||
disabled={isStudent}
|
|
||||||
checked={$attendance[student.id]
|
|
||||||
? $attendance[student.id][lesson.id]
|
|
||||||
? $attendance[student.id][lesson.id].is_present
|
|
||||||
: false
|
|
||||||
: false}
|
|
||||||
on:change={(e) => handleAttendanceChange(e, student, lesson)}
|
|
||||||
/>
|
|
||||||
</StructuredListCell>
|
|
||||||
{/each}
|
{/each}
|
||||||
</StructuredListRow>
|
</StructuredListRow>
|
||||||
</StructuredListBody>
|
</StructuredListHead>
|
||||||
{/each}
|
|
||||||
</StructuredList>
|
{#each searchStudents(searchValue) as student}
|
||||||
{#if students.length === 0}
|
<StructuredListBody>
|
||||||
<div>
|
<StructuredListRow>
|
||||||
<Box>
|
<StructuredListCell>
|
||||||
|
<div class="w-1/4 flex items-center">
|
||||||
|
<p class="dark:text-white font-semibold">
|
||||||
|
{student.profile.fullname}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</StructuredListCell>
|
||||||
|
{#each $lessons as lesson}
|
||||||
|
<StructuredListCell class="">
|
||||||
|
<Checkbox
|
||||||
|
class={isStudent && 'cursor-not-allowed'}
|
||||||
|
disabled={isStudent}
|
||||||
|
checked={$attendance[student.id]
|
||||||
|
? $attendance[student.id][lesson.id]
|
||||||
|
? $attendance[student.id][lesson.id].is_present
|
||||||
|
: false
|
||||||
|
: false}
|
||||||
|
on:change={(e) => handleAttendanceChange(e, student, lesson)}
|
||||||
|
/>
|
||||||
|
</StructuredListCell>
|
||||||
|
{/each}
|
||||||
|
</StructuredListRow>
|
||||||
|
</StructuredListBody>
|
||||||
|
{/each}
|
||||||
|
</StructuredList>
|
||||||
|
{#if students.length === 0}
|
||||||
|
<Box className="h-[300px] w-full">
|
||||||
<AudioConsoleIcon size={32} class="carbon-icon w-80" />
|
<AudioConsoleIcon size={32} class="carbon-icon w-80" />
|
||||||
<h3 class="text-3xl text-gray-500 dark:text-white">No Student Added</h3>
|
<h3 class="text-3xl text-gray-500 dark:text-white text-center">No Student Added</h3>
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
{/if}
|
||||||
{/if}
|
{#if students.length !== 0}
|
||||||
<Pagination totalItems={10} pageSizes={[10, 15, 20]} />
|
<Pagination totalItems={10} pageSizes={[10, 15, 20]} />
|
||||||
</section>
|
{/if}
|
||||||
|
</section>
|
||||||
|
</PageBody>
|
||||||
</CourseContainer>
|
</CourseContainer>
|
||||||
|
|||||||
@@ -30,12 +30,12 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="root absolute inset-0 flex justify-center items-center z-50 bg-white"
|
class="absolute inset-0 z-50 bg-white"
|
||||||
in:fly={{ y: 500, duration: 500 }}
|
in:fly={{ y: 500, duration: 500 }}
|
||||||
out:fly={{ y: 500, duration: 500 }}
|
out:fly={{ y: 500, duration: 500 }}
|
||||||
>
|
>
|
||||||
<Editor {courseId} bind:course={courseData} />
|
<Editor {courseId} bind:course={courseData} />
|
||||||
<div class="rightBar" class:isMobile={$isMobile}>
|
<div class="rightBar">
|
||||||
<CourseLandingPage bind:courseData />
|
<CourseLandingPage bind:courseData />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,13 +43,8 @@
|
|||||||
<style>
|
<style>
|
||||||
.rightBar {
|
.rightBar {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
width: calc(100% - 360px);
|
width: 100%;
|
||||||
overflow: auto;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow-y: auto;
|
||||||
}
|
|
||||||
|
|
||||||
.rightBar.isMobile {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -321,12 +321,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<Box>
|
<Box>
|
||||||
<div class="flex justify-between flex-col items-center w-96">
|
<div class="flex justify-between flex-col items-center w-[90%] md:w-96">
|
||||||
<img src="/images/empty-lesson-icon.svg" alt="Lesson" class="my-2.5 mx-auto" />
|
<img src="/images/empty-lesson-icon.svg" alt="Lesson" class="my-2.5 mx-auto" />
|
||||||
<h2 class="text-xl my-1.5 font-normal">No lessons yet</h2>
|
<h2 class="text-xl my-1.5 font-normal">No lessons yet</h2>
|
||||||
<p class="text-sm text-center text-slate-500">
|
<p class="text-sm text-center text-slate-500">
|
||||||
Share your knowledge with the world by creating engaging lessons. Start by clicking on
|
Share your knowledge with the world by creating engaging lessons. Start by clicking on
|
||||||
the New Lesson button.
|
the Add button.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -4,17 +4,19 @@
|
|||||||
import { fetchCourse, fetchLesson } from '$lib/utils/services/courses';
|
import { fetchCourse, fetchLesson } from '$lib/utils/services/courses';
|
||||||
import CheckmarkOutlineIcon from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
|
import CheckmarkOutlineIcon from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
|
||||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants.js';
|
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||||
import { Loading } from 'carbon-components-svelte';
|
import { Loading } from 'carbon-components-svelte';
|
||||||
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
|
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
|
||||||
import PageNav from '$lib/components/PageNav/index.svelte';
|
import PageNav from '$lib/components/PageNav/index.svelte';
|
||||||
import PageBody from '$lib/components/PageBody/index.svelte';
|
import PageBody from '$lib/components/PageBody/index.svelte';
|
||||||
import Materials from '$lib/components/Course/components/Lesson/Materials/index.svelte';
|
import Materials from '$lib/components/Course/components/Lesson/Materials/index.svelte';
|
||||||
import Exercises from '$lib/components/Course/components/Lesson/Exercises/index.svelte';
|
import Exercises from '$lib/components/Course/components/Lesson/Exercises/index.svelte';
|
||||||
import MODES from '$lib/utils/constants/mode.js';
|
import MODES from '$lib/utils/constants/mode';
|
||||||
import { setCourse, course } from '$lib/components/Course/store';
|
import { setCourse, course } from '$lib/components/Course/store';
|
||||||
import Download from 'carbon-icons-svelte/lib/Download.svelte';
|
import Download from 'carbon-icons-svelte/lib/Download.svelte';
|
||||||
|
import OverflowMenuVertical from 'carbon-icons-svelte/lib/OverflowMenuVertical.svelte';
|
||||||
|
import { apps } from '$lib/components/Apps/store';
|
||||||
|
import IconButton from '$lib/components/IconButton/index.svelte';
|
||||||
import {
|
import {
|
||||||
lesson,
|
lesson,
|
||||||
lessons,
|
lessons,
|
||||||
@@ -144,6 +146,10 @@
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleApps = () => {
|
||||||
|
$apps.open = !$apps.open;
|
||||||
|
};
|
||||||
|
|
||||||
function toggleMode() {
|
function toggleMode() {
|
||||||
prevMode = mode;
|
prevMode = mode;
|
||||||
mode = mode === MODES.edit ? MODES.view : MODES.edit;
|
mode = mode === MODES.edit ? MODES.view : MODES.edit;
|
||||||
@@ -176,9 +182,20 @@
|
|||||||
<svelte:fragment slot="widget">
|
<svelte:fragment slot="widget">
|
||||||
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
||||||
{#if data.isMaterialsTabActive}
|
{#if data.isMaterialsTabActive}
|
||||||
<div class="flex items-center">
|
<div class="lg:hidden">
|
||||||
|
<IconButton onClick={toggleApps} buttonClassName="">
|
||||||
|
<OverflowMenuVertical size={24} />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class={`flex-row ${
|
||||||
|
$apps.dropdown && $apps.open
|
||||||
|
? 'absolute lg:relative top-[85px] lg:top-0 right-14 lg:right-0 z-40 dark:bg-gray-800 p-3 lg:p-0'
|
||||||
|
: 'hidden'
|
||||||
|
} lg:flex items-center`}
|
||||||
|
>
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
className="mr-2"
|
className="mb-2 lg:mb-0 mr-2"
|
||||||
variant={VARIANTS.OUTLINED}
|
variant={VARIANTS.OUTLINED}
|
||||||
onClick={downloadLesson}
|
onClick={downloadLesson}
|
||||||
{isLoading}
|
{isLoading}
|
||||||
@@ -207,7 +224,7 @@
|
|||||||
<PageBody>
|
<PageBody>
|
||||||
<Materials lessonId={data.lessonId} {mode} {prevMode} {toggleMode} bind:isSaving />
|
<Materials lessonId={data.lessonId} {mode} {prevMode} {toggleMode} bind:isSaving />
|
||||||
|
|
||||||
<div class="w-full flex flex-row-reverse">
|
<div class="w-full flex flex-row-reverse mt-10">
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
onClick={markLessonComplete}
|
onClick={markLessonComplete}
|
||||||
isLoading={isMarkingComplete}
|
isLoading={isMarkingComplete}
|
||||||
|
|||||||
@@ -8,10 +8,7 @@
|
|||||||
import { ROLE } from '$lib/utils/constants/roles';
|
import { ROLE } from '$lib/utils/constants/roles';
|
||||||
import { setCourse, course, group } from '$lib/components/Course/store';
|
import { setCourse, course, group } from '$lib/components/Course/store';
|
||||||
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
|
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
|
||||||
import {
|
import { fetchCourse, fetchExercisesByMarks } from '$lib/utils/services/courses';
|
||||||
fetchCourse,
|
|
||||||
fetchExercisesByMarks,
|
|
||||||
} from '$lib/utils/services/courses';
|
|
||||||
import { getLectureNo } from '$lib/components/Course/function';
|
import { getLectureNo } from '$lib/components/Course/function';
|
||||||
import { fetchMarks } from '$lib/utils/services/marks';
|
import { fetchMarks } from '$lib/utils/services/marks';
|
||||||
import { profile } from '$lib/utils/store/user';
|
import { profile } from '$lib/utils/store/user';
|
||||||
@@ -19,10 +16,8 @@
|
|||||||
export let data;
|
export let data;
|
||||||
const { courseId } = data;
|
const { courseId } = data;
|
||||||
|
|
||||||
let borderBottomGrey =
|
let borderBottomGrey = 'border-r-0 border-t-0 border-b border-l-0 border-gray-300';
|
||||||
'border-r-0 border-t-0 border-b border-l-0 border-gray-300';
|
let borderleftGrey = 'border-r-0 border-t-0 border-b-0 border-l border-gray-300';
|
||||||
let borderleftGrey =
|
|
||||||
'border-r-0 border-t-0 border-b-0 border-l border-gray-300';
|
|
||||||
let students = [];
|
let students = [];
|
||||||
let isStudent = false;
|
let isStudent = false;
|
||||||
|
|
||||||
@@ -52,11 +47,11 @@
|
|||||||
if (studentMarksByExerciseId[groupmember_id]) {
|
if (studentMarksByExerciseId[groupmember_id]) {
|
||||||
studentMarksByExerciseId[groupmember_id] = {
|
studentMarksByExerciseId[groupmember_id] = {
|
||||||
...studentMarksByExerciseId[groupmember_id],
|
...studentMarksByExerciseId[groupmember_id],
|
||||||
[exercise_id]: total_points_gotten,
|
[exercise_id]: total_points_gotten
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
studentMarksByExerciseId[groupmember_id] = {
|
studentMarksByExerciseId[groupmember_id] = {
|
||||||
[exercise_id]: total_points_gotten,
|
[exercise_id]: total_points_gotten
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -70,11 +65,11 @@
|
|||||||
if (lessonMapping[lesson_id]) {
|
if (lessonMapping[lesson_id]) {
|
||||||
lessonMapping[lesson_id] = {
|
lessonMapping[lesson_id] = {
|
||||||
...lessonMapping[lesson_id],
|
...lessonMapping[lesson_id],
|
||||||
[exercise_id]: { title: exercise_title, points },
|
[exercise_id]: { title: exercise_title, points }
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
lessonMapping[lesson_id] = {
|
lessonMapping[lesson_id] = {
|
||||||
[exercise_id]: { title: exercise_title, points },
|
[exercise_id]: { title: exercise_title, points }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -82,20 +77,16 @@
|
|||||||
|
|
||||||
$: {
|
$: {
|
||||||
students = isStudent
|
students = isStudent
|
||||||
? $group.people.filter(
|
? $group.people.filter((person) => !!person.profile && person.profile.id === $profile.id)
|
||||||
(person) => !!person.profile && person.profile.id === $profile.id
|
: $group.people.filter((person) => !!person.profile && person.role_id === ROLE.STUDENT);
|
||||||
)
|
|
||||||
: $group.people.filter(
|
|
||||||
(person) => !!person.profile && person.role_id === ROLE.STUDENT
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<CourseContainer bind:isStudent>
|
<CourseContainer bind:isStudent>
|
||||||
<PageNav title="Marks" />
|
<PageNav title="Marks" />
|
||||||
|
|
||||||
<PageBody width="w-11/12">
|
<PageBody width="w-full max-w-6xl md:w-11/12">
|
||||||
<div class="table rounded-md border border-gray-300 w-auto">
|
<div class="table rounded-md border border-gray-300 w-full">
|
||||||
<div class="flex items-center {borderBottomGrey}">
|
<div class="flex items-center {borderBottomGrey}">
|
||||||
<div class="box flex items-center p-3">
|
<div class="box flex items-center p-3">
|
||||||
<p class="dark:text-white w-40">Student</p>
|
<p class="dark:text-white w-40">Student</p>
|
||||||
@@ -111,8 +102,7 @@
|
|||||||
>
|
>
|
||||||
{#each Object.keys(lessonMapping[lesson.id]) as exerciseId, index}
|
{#each Object.keys(lessonMapping[lesson.id]) as exerciseId, index}
|
||||||
<p
|
<p
|
||||||
class="col text-sm dark:text-white {index &&
|
class="col text-sm dark:text-white {index && borderleftGrey}"
|
||||||
borderleftGrey}"
|
|
||||||
title={lessonMapping[lesson.id][exerciseId].title}
|
title={lessonMapping[lesson.id][exerciseId].title}
|
||||||
>
|
>
|
||||||
{lessonMapping[lesson.id][exerciseId].title}
|
{lessonMapping[lesson.id][exerciseId].title}
|
||||||
@@ -129,9 +119,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#each students as student}
|
{#each students as student}
|
||||||
<div
|
<div class="flex relative items-center p-3 cursor-pointer {borderBottomGrey}">
|
||||||
class="flex relative items-center p-3 cursor-pointer {borderBottomGrey}"
|
|
||||||
>
|
|
||||||
<div class="w-40 flex items-center">
|
<div class="w-40 flex items-center">
|
||||||
<img
|
<img
|
||||||
alt="Student avatar"
|
alt="Student avatar"
|
||||||
@@ -143,11 +131,7 @@
|
|||||||
{student.profile.fullname}
|
{student.profile.fullname}
|
||||||
</p>
|
</p>
|
||||||
<p class="dark:text-white">
|
<p class="dark:text-white">
|
||||||
{`${
|
{`${student.assigned_student_id ? '#' + student.assigned_student_id : '-'}`}
|
||||||
student.assigned_student_id
|
|
||||||
? '#' + student.assigned_student_id
|
|
||||||
: '-'
|
|
||||||
}`}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -176,9 +160,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<Box>
|
<Box>
|
||||||
<AudioConsoleIcon size={32} class="carbon-icon w-80" />
|
<AudioConsoleIcon size={32} class="carbon-icon w-80" />
|
||||||
<h3 class="text-3xl text-gray-500 dark:text-white">
|
<h3 class="text-3xl text-gray-500 dark:text-white">No Student Added</h3>
|
||||||
No Student Added
|
|
||||||
</h3>
|
|
||||||
</Box>
|
</Box>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import TextChip from '$lib/components/Chip/Text.svelte';
|
import TextChip from '$lib/components/Chip/Text.svelte';
|
||||||
import ComingSoon from '$lib/components/ComingSoon/index.svelte';
|
import ComingSoon from '$lib/components/ComingSoon/index.svelte';
|
||||||
|
import Filter from 'carbon-icons-svelte/lib/Filter.svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import copy from 'copy-to-clipboard';
|
import copy from 'copy-to-clipboard';
|
||||||
import {
|
import {
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
import { fetchCourse, deleteGroupMember, updatedGroupMember } from '$lib/utils/services/courses';
|
import { fetchCourse, deleteGroupMember, updatedGroupMember } from '$lib/utils/services/courses';
|
||||||
import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte';
|
import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte';
|
||||||
import PageNav from '$lib/components/PageNav/index.svelte';
|
import PageNav from '$lib/components/PageNav/index.svelte';
|
||||||
|
import PageBody from '$lib/components/PageBody/index.svelte';
|
||||||
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
||||||
import Select from '$lib/components/Form/Select.svelte';
|
import Select from '$lib/components/Form/Select.svelte';
|
||||||
import IconButton from '$lib/components/IconButton/index.svelte';
|
import IconButton from '$lib/components/IconButton/index.svelte';
|
||||||
@@ -135,138 +137,148 @@
|
|||||||
</RoleBasedSecurity>
|
</RoleBasedSecurity>
|
||||||
</slot:fragment>
|
</slot:fragment>
|
||||||
</PageNav>
|
</PageNav>
|
||||||
<section class="my-5 mx-9">
|
<PageBody width="w-full max-w-6xl md:w-11/12">
|
||||||
<div class="flex flex-row flex-end justify-end items-center mb-7">
|
<section class="my-5 mx-2 md:mx-9">
|
||||||
<div class="mr-5 w-80">
|
<div
|
||||||
<Search
|
class="flex flex-col md:flex-row flex-end gap-2 justify-end items-start md:items-center mb-7"
|
||||||
class="dark:text-slate-950 border-0 bg-zinc-100 w-full"
|
|
||||||
placeholder="Search people"
|
|
||||||
bind:value={searchValue}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<Select bind:value={filterBy} options={ROLES} className="dark:text-black mt-3 w-20" />
|
|
||||||
<!-- <select bind:value={filterBy} class="mt-3">
|
|
||||||
{#each ROLES as option}
|
|
||||||
<option value={option.value}>{option.label}</option>
|
|
||||||
{/each}
|
|
||||||
</select> -->
|
|
||||||
</div>
|
|
||||||
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
|
||||||
<p class="dark:text-white hidden lg:block text-lg w-20" />
|
|
||||||
</RoleBasedSecurity>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<StructuredList class="m-0">
|
|
||||||
<StructuredListHead
|
|
||||||
class="bg-slate-100 dark:bg-neutral-800 dark:border-2 dark:border-neutral-800"
|
|
||||||
>
|
>
|
||||||
<StructuredListRow head class="mx-7">
|
<div class="max-w-[320px]">
|
||||||
<StructuredListCell head class="text-primary-700 py-3 dark:text-white"
|
<Search
|
||||||
>Name</StructuredListCell
|
class="dark:text-slate-950 border-0 bg-zinc-100 w-full"
|
||||||
>
|
placeholder="Search people"
|
||||||
<StructuredListCell head class="text-primary-700 py-3 dark:text-white"
|
bind:value={searchValue}
|
||||||
>Role</StructuredListCell
|
/>
|
||||||
>
|
</div>
|
||||||
<StructuredListCell head class="text-primary-700 py-3 dark:text-white"
|
<div class="mb-3">
|
||||||
>Action</StructuredListCell
|
<Select
|
||||||
>
|
bind:value={filterBy}
|
||||||
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
options={ROLES}
|
||||||
<p class="dark:text-white hidden lg:block text-lg w-20" />
|
className="dark:text-black mt-3 max-w-[80px]"
|
||||||
</RoleBasedSecurity>
|
/>
|
||||||
</StructuredListRow>
|
<!-- <select bind:value={filterBy} class="mt-3">
|
||||||
</StructuredListHead>
|
{#each ROLES as option}
|
||||||
|
<option value={option.value}>{option.label}</option>
|
||||||
|
{/each}
|
||||||
|
</select> -->
|
||||||
|
</div>
|
||||||
|
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
||||||
|
<p class="dark:text-white hidden lg:block text-lg w-20" />
|
||||||
|
</RoleBasedSecurity>
|
||||||
|
</div>
|
||||||
|
|
||||||
{#each filterPeople(searchValue, people) as person}
|
<StructuredList class="m-0">
|
||||||
<StructuredListBody>
|
<StructuredListHead
|
||||||
<StructuredListRow class="relative">
|
class="bg-slate-100 dark:bg-neutral-800 dark:border-2 dark:border-neutral-800"
|
||||||
<!-- first column -->
|
>
|
||||||
<StructuredListCell class="w-3/6">
|
<StructuredListRow head class="mx-7">
|
||||||
{#if person.profile}
|
<StructuredListCell head class="text-primary-700 py-3 dark:text-white"
|
||||||
<div class="flex items-center absolute bottom-3">
|
>Name</StructuredListCell
|
||||||
<Avatar
|
>
|
||||||
src={person.profile.avatar_url}
|
<StructuredListCell head class="text-primary-700 py-3 dark:text-white"
|
||||||
name={person.profile.fullname}
|
>Role</StructuredListCell
|
||||||
width="w-8"
|
>
|
||||||
height="h-8"
|
<StructuredListCell head class="text-primary-700 py-3 dark:text-white"
|
||||||
className="mr-3"
|
>Action</StructuredListCell
|
||||||
/>
|
>
|
||||||
<div class="flex items-center">
|
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
||||||
<div class="mr-2">
|
<p class="dark:text-white hidden lg:block text-lg w-20" />
|
||||||
<p class="dark:text-white text-base font-normal">
|
</RoleBasedSecurity>
|
||||||
{person.profile.fullname}
|
</StructuredListRow>
|
||||||
</p>
|
</StructuredListHead>
|
||||||
<p class="text-xs text-primary-600">
|
|
||||||
{getEmail(person)}
|
{#each filterPeople(searchValue, people) as person}
|
||||||
</p>
|
<StructuredListBody>
|
||||||
</div>
|
<StructuredListRow class="relative">
|
||||||
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
<!-- first column -->
|
||||||
<div class="hidden lg:flex lg:justify-between lg:items-center mr-2">
|
<StructuredListCell class="w-4/6 md:w-3/6">
|
||||||
<CopyButton text={getEmail(person)} feedback="Copied Email to clipboard" />
|
{#if person.profile}
|
||||||
|
<div class="flex items-start lg:items-center">
|
||||||
|
<Avatar
|
||||||
|
src={person.profile.avatar_url}
|
||||||
|
name={person.profile.fullname}
|
||||||
|
width="w-8"
|
||||||
|
height="h-8"
|
||||||
|
className="mr-3"
|
||||||
|
/>
|
||||||
|
<div class="flex flex-col lg:flex-row items-start lg:items-center">
|
||||||
|
<div class="mr-2">
|
||||||
|
<p class="dark:text-white text-base font-normal">
|
||||||
|
{person.profile.fullname}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-primary-600 line-clamp-1">
|
||||||
|
{getEmail(person)}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</RoleBasedSecurity>
|
<div class="flex items-center">
|
||||||
{#if person.profile_id == $profile.id}
|
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
||||||
<ComingSoon label="You" />
|
<CopyButton
|
||||||
|
text={getEmail(person)}
|
||||||
|
feedback="Copied Email to clipboard"
|
||||||
|
/>
|
||||||
|
</RoleBasedSecurity>
|
||||||
|
{#if person.profile_id == $profile.id}
|
||||||
|
<ComingSoon label="You" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="flex items-start lg:items-center w-2/4">
|
||||||
|
<TextChip
|
||||||
|
value={person.email.substring(0, 2).toUpperCase()}
|
||||||
|
className="bg-primary-200 text-black font-semibold text-xs mr-3"
|
||||||
|
shape="rounded-full"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
href="mailto:{person.email}"
|
||||||
|
class="text-md text-primary-600 mr-2 dark:text-white"
|
||||||
|
>
|
||||||
|
{person.email}
|
||||||
|
</a>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
||||||
|
<CopyButton text={getEmail(person)} feedback="Copied Email to clipboard" />
|
||||||
|
</RoleBasedSecurity>
|
||||||
|
|
||||||
|
<TextChip
|
||||||
|
value="Pending"
|
||||||
|
className="text-xs bg-yellow-200 text-yellow-700 h-fit"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</StructuredListCell>
|
||||||
|
|
||||||
|
<!-- second column -->
|
||||||
|
<StructuredListCell class="w-1/4 px-3">
|
||||||
|
<p class=" dark:text-white font-normal text-center text-base w-1/4">
|
||||||
|
{ROLE_LABEL[person.role_id]}
|
||||||
|
</p>
|
||||||
|
</StructuredListCell>
|
||||||
|
|
||||||
|
<!-- third column -->
|
||||||
|
<StructuredListCell class="p-0 w-1/4">
|
||||||
|
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
||||||
|
<div class="hidden lg:flex lg:justify-between lg:items-center w-20">
|
||||||
|
{#if person.profile_id !== $profile.id}
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
member = person;
|
||||||
|
$deleteMemberModal.open = true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TrashCanIcon size={16} class="carbon-icon dark:text-white" />
|
||||||
|
</IconButton>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</RoleBasedSecurity>
|
||||||
{:else}
|
</StructuredListCell>
|
||||||
<div class="flex items-center w-2/4 absolute bottom-3">
|
</StructuredListRow>
|
||||||
<TextChip
|
</StructuredListBody>
|
||||||
value={person.email.substring(0, 2).toUpperCase()}
|
{/each}
|
||||||
className="bg-primary-200 text-black font-semibold text-xs mr-3"
|
</StructuredList>
|
||||||
shape="rounded-full"
|
<!-- <Pagination totalItems={10} pageSizes={[10, 15, 20]} /> -->
|
||||||
/>
|
</section>
|
||||||
<a
|
</PageBody>
|
||||||
href="mailto:{person.email}"
|
|
||||||
class="text-md text-primary-600 mr-2 dark:text-white"
|
|
||||||
>
|
|
||||||
{person.email}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
|
||||||
<div class="hidden lg:flex lg:justify-between lg:items-center w-20">
|
|
||||||
<CopyButton text={getEmail(person)} feedback="Copied Email to clipboard" />
|
|
||||||
</div>
|
|
||||||
</RoleBasedSecurity>
|
|
||||||
|
|
||||||
<TextChip
|
|
||||||
value="Pending"
|
|
||||||
className="text-xs bg-yellow-200 text-yellow-700 h-fit"
|
|
||||||
size="sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</StructuredListCell>
|
|
||||||
|
|
||||||
<!-- second column -->
|
|
||||||
<StructuredListCell class="w-1/4 py-4 px-3">
|
|
||||||
<p class="dark:text-white font-normal text-base w-1/4 my-auto">
|
|
||||||
{ROLE_LABEL[person.role_id]}
|
|
||||||
</p>
|
|
||||||
</StructuredListCell>
|
|
||||||
|
|
||||||
<!-- third column -->
|
|
||||||
<StructuredListCell class="p-0 w-1/4">
|
|
||||||
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
|
||||||
<div class="hidden lg:flex lg:justify-between lg:items-center w-20">
|
|
||||||
{#if person.profile_id !== $profile.id}
|
|
||||||
<IconButton
|
|
||||||
onClick={() => {
|
|
||||||
member = person;
|
|
||||||
$deleteMemberModal.open = true;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TrashCanIcon size={16} class="carbon-icon dark:text-white" />
|
|
||||||
</IconButton>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</RoleBasedSecurity>
|
|
||||||
</StructuredListCell>
|
|
||||||
</StructuredListRow>
|
|
||||||
</StructuredListBody>
|
|
||||||
{/each}
|
|
||||||
</StructuredList>
|
|
||||||
<Pagination totalItems={10} pageSizes={[10, 15, 20]} />
|
|
||||||
</section>
|
|
||||||
</CourseContainer>
|
</CourseContainer>
|
||||||
|
|||||||
@@ -244,8 +244,8 @@
|
|||||||
<CourseContainer>
|
<CourseContainer>
|
||||||
<PageNav title="Submitted Exercises" />
|
<PageNav title="Submitted Exercises" />
|
||||||
|
|
||||||
<PageBody width="w-11/12 overflow-x-auto overflow-y-hidden">
|
<PageBody width="w-full max-w-6xl md:w-11/12 overflow-x-auto">
|
||||||
<div class="flex items-center w-full">
|
<div class="flex items-center w-full overflow-x-scroll">
|
||||||
{#each sections as { id, title, items }, idx (id)}
|
{#each sections as { id, title, items }, idx (id)}
|
||||||
<div
|
<div
|
||||||
class="section rounded-md bg-gray-100 dark:bg-gray-800 border border-gray-50 p-3 h-80 mr-3 overflow-hidden"
|
class="section rounded-md bg-gray-100 dark:bg-gray-800 border border-gray-50 p-3 h-80 mr-3 overflow-hidden"
|
||||||
@@ -301,7 +301,7 @@
|
|||||||
{`${item.tutor ? 'created by' + item.tutor.name : ''}`}
|
{`${item.tutor ? 'created by' + item.tutor.name : ''}`}
|
||||||
</p>
|
</p>
|
||||||
</a>
|
</a>
|
||||||
<p class="dark:text-white text-gray-500 dark:text-white text-xs">
|
<p class="dark:text-white text-gray-500 text-xs">
|
||||||
{item.submittedAt}
|
{item.submittedAt}
|
||||||
</p>
|
</p>
|
||||||
<!-- <div class="badge rounded-md px-2 bg-green-500 text-white">
|
<!-- <div class="badge rounded-md px-2 bg-green-500 text-white">
|
||||||
@@ -324,10 +324,15 @@
|
|||||||
.section {
|
.section {
|
||||||
max-width: 355px;
|
max-width: 355px;
|
||||||
min-width: 355px;
|
min-width: 355px;
|
||||||
height: 80vh;
|
height: 75vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
height: 95%;
|
height: 95%;
|
||||||
}
|
}
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.section {
|
||||||
|
min-width: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user