CLASSROOMIO-T-255: Fix course sidebar bug

CLASSROOMIO-T-255: Lesson page UX improvements

CLASSROOMIO-T-255:Updated part of the code

CLASSROOMIO-T-255:Worked on the sidebar

CLASSROOMIO-T-255:Worked on the sidebar

CLASSROOMIO-T-255:Worked on the sidebar

CLASSROOMIO-T-255:Worked on the sidebar and the appbar


Co-authored-by: Ifeanyi Nwosu <[email protected]>
Co-authored-by: Rotimi Best <[email protected]>


Merge-request: CLASSROOMIO-MR-117
Merged-by: Best Admin <[email protected]>
This commit is contained in:
emmanuel
2023-11-01 09:45:40 +00:00
committed by Space Cloud
co-authored by Rotimi Best
parent 53bd8c1b6b
commit 80cb9a5672
14 changed files with 79 additions and 72 deletions
@@ -149,7 +149,7 @@
} }
</script> </script>
<PageNav title="Poll" overidableStyle="padding: 0 10px"> <PageNav title="Poll" overidableStyle="padding: 0 10px" paddingClass="w-full">
<div slot="widget"> <div slot="widget">
<CloseButton onClick={handleClose} /> <CloseButton onClick={handleClose} />
</div> </div>
+4 -6
View File
@@ -40,7 +40,7 @@
} else { } else {
$apps.selectedApp = appName; $apps.selectedApp = appName;
} }
$apps.dropdown = false; $apps.dropdown = !$apps.dropdown;
} }
function updateTopPadding(isStudent: boolean) { function updateTopPadding(isStudent: boolean) {
@@ -91,7 +91,6 @@
toolTipProps={{ title: 'Settings', hotkeys: ['A', '0'] }} toolTipProps={{ title: 'Settings', hotkeys: ['A', '0'] }}
onClick={() => { onClick={() => {
handleAppClick(); handleAppClick();
$apps.dropdown = !$apps.dropdown;
}} }}
> >
<Settings size={24} class="carbon-icon dark:text-white lg:hidden" /> <Settings size={24} class="carbon-icon dark:text-white lg:hidden" />
@@ -194,9 +193,7 @@
@media screen and (min-width: 768px) and (max-width: 1023px) { @media screen and (min-width: 768px) and (max-width: 1023px) {
.app { .app {
min-width: 280px; width: 50vw;
max-width: 300px;
width: 300px;
position: relative; position: relative;
overflow: auto; overflow: auto;
} }
@@ -204,7 +201,8 @@
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
.app { .app {
width: 100%; width: 100vw;
min-width: calc(100vw - 60px);
position: relative; position: relative;
overflow: auto; overflow: auto;
} }
@@ -17,7 +17,7 @@
</script> </script>
{#if !isNoteEmpty($lesson.materials?.note)} {#if !isNoteEmpty($lesson.materials?.note)}
<HtmlRender> <HtmlRender className="m-auto">
<svelte:fragment slot="content"> <svelte:fragment slot="content">
<div> <div>
{@html $lesson.materials.note} {@html $lesson.materials.note}
@@ -36,6 +36,7 @@
import HtmlRender from '$lib/components/HTMLRender/HTMLRender.svelte'; import HtmlRender from '$lib/components/HTMLRender/HTMLRender.svelte';
import type { LessonPage } from '$lib/utils/types'; import type { LessonPage } from '$lib/utils/types';
import { getTextFromHTML } from '$lib/utils/functions/course'; import { getTextFromHTML } from '$lib/utils/functions/course';
import { snackbar } from '$lib/components/Snackbar/store';
export let mode = MODES.view; export let mode = MODES.view;
export let prevMode = ''; export let prevMode = '';
@@ -75,7 +76,7 @@
materials materials
} }
: $lesson; : $lesson;
handleUpdateLessonMaterials(_lesson, lessonId); return handleUpdateLessonMaterials(_lesson, lessonId);
} }
function isNoteEmpty(note: string) { function isNoteEmpty(note: string) {
@@ -178,7 +179,12 @@
isSaving = true; isSaving = true;
timeoutId = setTimeout(async () => { timeoutId = setTimeout(async () => {
await saveLesson(updatedMaterials); const { error } = await saveLesson(updatedMaterials);
if (error) {
console.log('error saving lesson', error);
snackbar.error('We apologise, there was an error saving your lesson.');
}
isSaving = false; isSaving = false;
}, 500); }, 500);
} }
@@ -244,9 +250,9 @@
<VideoUploader {lessonId} /> <VideoUploader {lessonId} />
</Modal> </Modal>
<HtmlRender> <HtmlRender className="m-auto text-center">
<svelte:fragment slot="content"> <svelte:fragment slot="content">
<h1 class="text-4xl mt-0 capitalize"> <h1 class="text-2xl md:text-4xl mt-0 capitalize">
{lessonTitle} {lessonTitle}
</h1> </h1>
</svelte:fragment> </svelte:fragment>
@@ -13,7 +13,7 @@
import { course } from '$lib/components/Course/store'; import { course } from '$lib/components/Course/store';
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, sideBar } from '$lib/components/Org/store'; import { sideBar } from '$lib/components/Org/store';
import { profile } from '$lib/utils/store/user'; import { profile } from '$lib/utils/store/user';
import { getIsLessonComplete } from '../Lesson/functions'; import { getIsLessonComplete } from '../Lesson/functions';
@@ -38,7 +38,9 @@
let menuContentRef; let menuContentRef;
const toggleSidebar = () => { const toggleSidebar = () => {
$menu.hidden = !$menu.hidden; if ($isMobile) {
$sideBar.hidden = !$sideBar.hidden;
}
}; };
function handleMainGroupClick(href: string) { function handleMainGroupClick(href: string) {
@@ -103,7 +105,7 @@
if (newWidth < 150) { if (newWidth < 150) {
sidebarRef.style.width = '0'; sidebarRef.style.width = '0';
menuContentRef.style.display = 'none'; menuContentRef.style.display = 'none';
$sideBar.open = false; $sideBar.hidden = true;
isDragging = false; isDragging = false;
resize = false; resize = false;
} else if (newWidth > window.innerWidth / 3 && window.innerWidth >= 1280) { } else if (newWidth > window.innerWidth / 3 && window.innerWidth >= 1280) {
@@ -231,21 +233,25 @@
</script> </script>
<aside <aside
class={`${ class={`
$menu.hidden ${
? '-translate-x-[100%] absolute md:translate-x-0 md:relative z-[40]' $sideBar.hidden
? '-translate-x-[100%] absolute z-[40]'
: 'translate-x-0 absolute md:relative z-[40]' : 'translate-x-0 absolute md:relative z-[40]'
} transition w-[90vw] md:w-[350px] bg-gray-100 dark:bg-black h-[calc(100vh-48px)] ${ }
transition w-[90vw] md:w-[300px] lg:w-[350px] bg-gray-100 dark:bg-black h-[calc(100vh-48px)]
${
resize && 'border-r-8 border-r-blue-500' resize && 'border-r-8 border-r-blue-500'
} overflow-y-auto border border-l-0 border-t-0 border-b-0 border-r-1`} } overflow-y-auto border border-l-0 border-t-0 border-b-0 border-r-1`}
style={$sideBar.open && 'width:0' ? 'width :300px' : 'width:0'} style={$sideBar.hidden === true ? 'width:0' : 'width:300px'}
bind:this={sidebarRef} bind:this={sidebarRef}
> >
<div class="sidebar-contenth-full flex flex-col"> <div class="sidebar-contenth-full flex flex-col">
<ul <ul
class="sidebar-content my-5" class="sidebar-content my-5"
style={$sideBar.open && 'width:0' ? 'display:block' : ''}
bind:this={menuContentRef} bind:this={menuContentRef}
style={$sideBar.hidden === true ? '' : 'display:block'}
> >
{#each navItems as navItem} {#each navItems as navItem}
{#if !navItem.show || (typeof navItem.show === 'function' && navItem.show())} {#if !navItem.show || (typeof navItem.show === 'function' && navItem.show())}
+1 -1
View File
@@ -48,7 +48,7 @@
$course.overview = html; $course.overview = html;
}} }}
placeholder="Write your overview here" placeholder="Write your overview here"
height="700" height={700}
/> />
{:else} {:else}
<HtmlRender className="p-2" content={$course.overview || ''} /> <HtmlRender className="p-2" content={$course.overview || ''} />
+3 -3
View File
@@ -9,7 +9,7 @@
import Avatar from '$lib/components/Avatar/index.svelte'; import Avatar from '$lib/components/Avatar/index.svelte';
import { profile } from '$lib/utils/store/user'; import { profile } from '$lib/utils/store/user';
import { NavClasses } from '$lib/utils/constants/reusableClass'; import { NavClasses } from '$lib/utils/constants/reusableClass';
import { menu } from '$lib/components/Org/store'; import { sideBar } from '$lib/components/Org/store';
function isActive(pagePath: string, itemPath: string) { function isActive(pagePath: string, itemPath: string) {
const pageLinkItems = pagePath.split('/'); const pageLinkItems = pagePath.split('/');
@@ -44,13 +44,13 @@
} }
]; ];
const toggleSidebar = () => { const toggleSidebar = () => {
$menu.hidden = !$menu.hidden; $sideBar.hidden = !$sideBar.hidden;
}; };
</script> </script>
<aside <aside
class={`${ class={`${
$menu.hidden $sideBar.hidden
? '-translate-x-[100%] absolute md:translate-x-0 md:relative z-40' ? '-translate-x-[100%] absolute md:translate-x-0 md:relative z-40'
: 'translate-x-0 absolute md:relative z-40' : 'translate-x-0 absolute md:relative z-40'
} overflow-y-auto transition w-[250px] min-w-[250px] bg-gray-100 dark:bg-neutral-900 h-[calc(100vh-48px)]`} } overflow-y-auto transition w-[250px] min-w-[250px] bg-gray-100 dark:bg-neutral-900 h-[calc(100vh-48px)]`}
+13 -9
View File
@@ -12,18 +12,14 @@
import { appStore } from '$lib/utils/store/app'; import { appStore } from '$lib/utils/store/app';
import { currentOrgPath } from '$lib/utils/store/org'; import { currentOrgPath } from '$lib/utils/store/org';
import { toggleBodyByMode } from '$lib/utils/functions/app'; import { toggleBodyByMode } from '$lib/utils/functions/app';
import { menu, sideBar } from '../Org/store'; import { sideBar } from '../Org/store';
export let title = ''; export let title = '';
export let navClass = ''; export let navClass = '';
export let isCoursePage = false; export let isCoursePage = false;
const toggleSidebar = () => { const toggleSidebar = () => {
$menu.hidden = !$menu.hidden; $sideBar.hidden = !$sideBar.hidden;
};
const openSidebar = () => {
$sideBar.open = !$sideBar.open;
}; };
function toggleDarkMode() { function toggleDarkMode() {
@@ -49,8 +45,12 @@
<ul class="flex w-full items-center"> <ul class="flex w-full items-center">
<div class="flex items-center text-white"> <div class="flex items-center text-white">
<li class="md:hidden"> <li class="md:hidden">
<IconButton onClick={toggleSidebar}> <IconButton
{#if $menu.hidden} onClick={() => {
toggleSidebar();
}}
>
{#if $sideBar.hidden}
<Menu size={16} class=" text-white" /> <Menu size={16} class=" text-white" />
{:else} {:else}
<Close size={16} class=" text-white" /> <Close size={16} class=" text-white" />
@@ -60,7 +60,11 @@
{#if isCoursePage} {#if isCoursePage}
<li class="hidden md:block"> <li class="hidden md:block">
<IconButton onClick={openSidebar}> <IconButton
onClick={() => {
toggleSidebar();
}}
>
<Menu size={16} class=" text-white" /> <Menu size={16} class=" text-white" />
</IconButton> </IconButton>
</li> </li>
+3 -3
View File
@@ -10,14 +10,14 @@
import IconButton from '$lib/components/IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
import { appStore } from '$lib/utils/store/app'; import { appStore } from '$lib/utils/store/app';
import { Close, Menu } from 'carbon-icons-svelte'; import { Close, Menu } from 'carbon-icons-svelte';
import { menu } from '$lib/components/Org/store'; import { sideBar } from '$lib/components/Org/store';
import { currentOrg } from '$lib/utils/store/org'; import { currentOrg } from '$lib/utils/store/org';
import { toggleBodyByMode } from '$lib/utils/functions/app'; import { toggleBodyByMode } from '$lib/utils/functions/app';
export let navClass = ''; export let navClass = '';
const toggleSidebar = () => { const toggleSidebar = () => {
$menu.hidden = !$menu.hidden; $sideBar.hidden = !$sideBar.hidden;
}; };
function toggleDarkMode() { function toggleDarkMode() {
@@ -38,7 +38,7 @@
<ul class="flex w-full items-center"> <ul class="flex w-full items-center">
<li class="md:hidden"> <li class="md:hidden">
<IconButton onClick={toggleSidebar}> <IconButton onClick={toggleSidebar}>
{#if $menu.hidden} {#if $sideBar.hidden}
<Menu size={16} class=" text-white" /> <Menu size={16} class=" text-white" />
{:else} {:else}
<Close size={16} class=" text-white" /> <Close size={16} class=" text-white" />
+3 -3
View File
@@ -14,7 +14,7 @@
import { currentOrg, currentOrgPath } from '$lib/utils/store/org'; import { currentOrg, currentOrgPath } from '$lib/utils/store/org';
import { profile } from '$lib/utils/store/user'; import { profile } from '$lib/utils/store/user';
import { NavClasses } from '$lib/utils/constants/reusableClass'; import { NavClasses } from '$lib/utils/constants/reusableClass';
import { menu } from './store'; import { sideBar } from './store';
const menuItems = [ const menuItems = [
{ {
@@ -54,13 +54,13 @@
return pagePath.includes(itemPath); return pagePath.includes(itemPath);
} }
const toggleSidebar = () => { const toggleSidebar = () => {
$menu.hidden = !$menu.hidden; $sideBar.hidden = !$sideBar.hidden;
}; };
</script> </script>
<aside <aside
class={`${ class={`${
$menu.hidden $sideBar.hidden
? '-translate-x-[100%] absolute md:translate-x-0 md:relative z-40' ? '-translate-x-[100%] absolute md:translate-x-0 md:relative z-40'
: 'translate-x-0 absolute md:relative z-40' : 'translate-x-0 absolute md:relative z-40'
} overflow-y-auto transition w-[250px] min-w-[250px] bg-gray-100 dark:bg-neutral-900 h-[calc(100vh-48px)] border border-l-0 border-t-0 border-b-0 border-r-1`} } overflow-y-auto transition w-[250px] min-w-[250px] bg-gray-100 dark:bg-neutral-900 h-[calc(100vh-48px)] border border-l-0 border-t-0 border-b-0 border-r-1`}
+1 -5
View File
@@ -1,13 +1,9 @@
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
export const menu = writable({
hidden: true
});
export const newOrgModal = writable({ export const newOrgModal = writable({
open: false open: false
}); });
export const sideBar = writable({ export const sideBar = writable({
open: true hidden: false
}); });
+20 -26
View File
@@ -1,15 +1,13 @@
<script lang="ts"> <script lang="ts">
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import InformationIcon from 'carbon-icons-svelte/lib/Information.svelte'; import { InlineNotification } from 'carbon-components-svelte';
import WarningIcon from 'carbon-icons-svelte/lib/Warning.svelte'; import { capitalizeFirstLetter } from '$lib/utils/functions/string';
import CheckmarkOutline24 from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
import CloseButton from '../Buttons/Close/index.svelte'; import { SNACKBAR_SEVERITY } from './constants';
import { SNACKBAR_SEVERITY, SNACKBAR_SEVERITY_COLOR } from './constants';
import { snackbarStore, snackbarStoreInitialState } from './store'; import { snackbarStore, snackbarStoreInitialState } from './store';
let severityColor: string;
let timeoutId: NodeJS.Timeout | undefined; let timeoutId: NodeJS.Timeout | undefined;
let kind: 'error' | 'info' | 'info-square' | 'success' | 'warning' | 'warning-alt' = 'info';
function handleClose() { function handleClose() {
if (typeof $snackbarStore.handleClose === 'function') { if (typeof $snackbarStore.handleClose === 'function') {
@@ -39,41 +37,37 @@
} }
$: handleOpen($snackbarStore.open); $: handleOpen($snackbarStore.open);
$: severityColor = SNACKBAR_SEVERITY_COLOR[$snackbarStore.severity]; $: kind =
$snackbarStore.severity === SNACKBAR_SEVERITY.SUCCESS
? 'success'
: $snackbarStore.severity === SNACKBAR_SEVERITY.ERROR
? 'error'
: 'info';
</script> </script>
{#if $snackbarStore.open} {#if $snackbarStore.open}
{#key $snackbarStore.message} {#key $snackbarStore.message}
<div <div transition:fly={{ x: 200, duration: 500 }} class="root absolute">
transition:fly={{ x: 200, duration: 500 }} <InlineNotification
class="root text-white rounded-md flex justify-between items-center absolute {severityColor}" {kind}
> title={capitalizeFirstLetter(kind || '')}
<div class="flex items-center"> subtitle={$snackbarStore.message}
{#if $snackbarStore.severity === SNACKBAR_SEVERITY.SUCCESS} on:close={(e) => {
<CheckmarkOutline24 size={24} class="carbon-icon dark:text-white" /> e.preventDefault();
{:else if $snackbarStore.severity === SNACKBAR_SEVERITY.WARNING} handleClose();
<WarningIcon size={24} class="carbon-icon dark:text-white" /> }}
{:else} />
<InformationIcon size={24} class="carbon-icon dark:text-white" />
{/if}
<p class="dark:text-white ml-2 text-lg">{$snackbarStore.message}</p>
</div>
<CloseButton onClick={handleClose} contained={true} color="text-white" />
</div> </div>
{/key} {/key}
{/if} {/if}
<style> <style>
.root { .root {
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
right: 5%; right: 5%;
left: auto; left: auto;
top: 24px; top: 24px;
transform: translateX(-5%); transform: translateX(-5%);
min-width: 288px; min-width: 288px;
padding: 6px 16px;
flex-wrap: wrap;
z-index: 51; z-index: 51;
} }
</style> </style>
+1 -1
View File
@@ -7,7 +7,7 @@
export let onChange = (html: string) => {}; export let onChange = (html: string) => {};
export let height = 300; export let height = 300;
export let placeholder = ''; export let placeholder = '';
export let editorWindowRef: Window; export let editorWindowRef: Window | undefined = undefined;
export let maxHeight: number | undefined = undefined; export let maxHeight: number | undefined = undefined;
const apiKey = PUBLIC_TINYMCE_API_KEY; const apiKey = PUBLIC_TINYMCE_API_KEY;
+3
View File
@@ -0,0 +1,3 @@
export function capitalizeFirstLetter(val: string): string {
return val.charAt(0).toUpperCase() + val.slice(1);
}