2021-05-22 22:25:33 +03:00
|
|
|
<script>
|
2023-10-03 14:51:02 +00:00
|
|
|
import { onDestroy, onMount } from 'svelte';
|
2021-07-18 19:12:39 +03:00
|
|
|
import hotkeys from 'hotkeys-js';
|
2023-08-02 19:35:27 +01:00
|
|
|
import Forum from 'carbon-icons-svelte/lib/Forum.svelte';
|
|
|
|
|
import AlignBoxTopLeft from 'carbon-icons-svelte/lib/AlignBoxTopLeft.svelte';
|
|
|
|
|
import SendAlt from 'carbon-icons-svelte/lib/SendAlt.svelte';
|
|
|
|
|
import ChartPie from 'carbon-icons-svelte/lib/ChartPie.svelte';
|
|
|
|
|
import IconButton from '$lib/components/IconButton/index.svelte';
|
2023-09-14 20:59:51 +00:00
|
|
|
import Settings from 'carbon-icons-svelte/lib/Settings.svelte';
|
|
|
|
|
import { apps } from './store';
|
2021-05-29 20:47:46 +03:00
|
|
|
|
2021-07-18 19:12:39 +03:00
|
|
|
import QandA from './components/QandA/index.svelte';
|
|
|
|
|
import LiveChat from './components/LiveChat/index.svelte';
|
|
|
|
|
import Notes from './components/Notes/index.svelte';
|
|
|
|
|
import Poll from './components/Poll/index.svelte';
|
|
|
|
|
import APPS_CONSTANTS from './constants';
|
2023-10-03 14:51:02 +00:00
|
|
|
import { browser } from '$app/environment';
|
2021-05-29 20:47:46 +03:00
|
|
|
|
2023-10-03 14:51:02 +00:00
|
|
|
let resize = false;
|
|
|
|
|
let isDragging = false;
|
|
|
|
|
let startX;
|
|
|
|
|
let initialWidth;
|
|
|
|
|
let appBarRef;
|
|
|
|
|
let appContentRef;
|
|
|
|
|
|
2023-10-06 12:49:40 +00:00
|
|
|
let topPadding = $apps.isStudent ? '48px' : '109px';
|
|
|
|
|
|
2023-10-04 08:18:33 +01:00
|
|
|
const getResizableSidebar = () => {
|
|
|
|
|
if (!browser) return;
|
|
|
|
|
|
|
|
|
|
return window.innerWidth >= 1024;
|
|
|
|
|
};
|
2021-05-29 20:47:46 +03:00
|
|
|
|
|
|
|
|
function handleClose() {
|
2023-10-06 12:49:40 +00:00
|
|
|
$apps.selectedApp = null;
|
2023-10-04 08:18:33 +01:00
|
|
|
if (getResizableSidebar()) {
|
2023-10-03 14:51:02 +00:00
|
|
|
appBarRef.style.width = '60px';
|
2023-10-06 12:49:40 +00:00
|
|
|
} else if (!getResizableSidebar() && $apps.isStudent) {
|
|
|
|
|
$apps.open = false;
|
2023-10-03 14:51:02 +00:00
|
|
|
}
|
2021-05-29 20:47:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleAppClick(appName) {
|
2023-10-06 12:49:40 +00:00
|
|
|
if (!$apps.selectedApp && getResizableSidebar()) {
|
2023-10-03 14:51:02 +00:00
|
|
|
if (window.innerWidth <= 1024) {
|
|
|
|
|
appBarRef.style.width = '300px';
|
|
|
|
|
} else {
|
2023-10-04 08:18:33 +01:00
|
|
|
appBarRef.style.width = '500px';
|
2023-10-03 14:51:02 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-10-06 12:49:40 +00:00
|
|
|
if (appName === $apps.selectedApp) {
|
2021-05-29 20:47:46 +03:00
|
|
|
handleClose();
|
|
|
|
|
} else {
|
2023-10-06 12:49:40 +00:00
|
|
|
$apps.selectedApp = appName;
|
2021-05-29 20:47:46 +03:00
|
|
|
}
|
2023-09-24 13:20:04 +00:00
|
|
|
$apps.dropdown = false;
|
2021-05-29 20:47:46 +03:00
|
|
|
}
|
2023-10-03 14:51:02 +00:00
|
|
|
|
|
|
|
|
function handleCursor(event) {
|
2023-10-04 08:18:33 +01:00
|
|
|
if (!getResizableSidebar()) return;
|
2023-10-06 12:49:40 +00:00
|
|
|
if (!resize && $apps.selectedApp) {
|
2023-10-03 14:51:02 +00:00
|
|
|
const isNearLeftBorder = event.clientX - appContentRef.getBoundingClientRect().left < 8;
|
|
|
|
|
const isNearRightBorder = appContentRef.getBoundingClientRect().right - event.clientX < 8;
|
|
|
|
|
|
|
|
|
|
if (isNearLeftBorder || isNearRightBorder) {
|
|
|
|
|
appContentRef.style.cursor = 'ew-resize';
|
|
|
|
|
} else {
|
|
|
|
|
appContentRef.style.cursor = 'auto';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function startDragging(event) {
|
2023-10-06 12:49:40 +00:00
|
|
|
if (event.button === 0 && $apps.selectedApp) {
|
2023-10-03 14:51:02 +00:00
|
|
|
event.preventDefault();
|
2023-10-05 10:32:57 +01:00
|
|
|
const isNearLeftBorder = event.clientX - appContentRef.getBoundingClientRect().left < 5;
|
|
|
|
|
const isNearRightBorder = appContentRef.getBoundingClientRect().right - event.clientX < 5;
|
2023-10-03 14:51:02 +00:00
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
(isNearRightBorder || isNearLeftBorder) &&
|
|
|
|
|
event.clientX >= 0 &&
|
|
|
|
|
event.clientX <= window.innerWidth
|
|
|
|
|
) {
|
|
|
|
|
isDragging = true;
|
|
|
|
|
resize = true;
|
|
|
|
|
startX = event.clientX;
|
|
|
|
|
initialWidth = parseInt(getComputedStyle(appBarRef).width, 10);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function stopDragging() {
|
|
|
|
|
isDragging = false;
|
|
|
|
|
resize = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function dragSidebar(event) {
|
2023-10-04 08:18:33 +01:00
|
|
|
if (!getResizableSidebar()) return;
|
2023-10-06 12:49:40 +00:00
|
|
|
if (!isDragging || !$apps.selectedApp) return;
|
2023-10-03 14:51:02 +00:00
|
|
|
const deltaX = startX - event.clientX + 60;
|
|
|
|
|
let newWidth = initialWidth + deltaX;
|
2023-10-05 10:32:57 +01:00
|
|
|
if (newWidth <= 250) {
|
2023-10-03 14:51:02 +00:00
|
|
|
handleClose();
|
|
|
|
|
appBarRef.style.width = '60px';
|
|
|
|
|
appContentRef.style.width = '0';
|
|
|
|
|
} else {
|
|
|
|
|
appBarRef.style.width = newWidth + 'px';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-06 12:49:40 +00:00
|
|
|
function updateTopPadding(isStudent) {
|
|
|
|
|
topPadding = isStudent ? '48px' : '109px';
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-31 11:28:46 +03:00
|
|
|
onMount(() => {
|
2023-10-06 12:49:40 +00:00
|
|
|
updateTopPadding($apps.isStudent);
|
2023-10-04 08:18:33 +01:00
|
|
|
if (getResizableSidebar()) {
|
2023-10-03 14:51:02 +00:00
|
|
|
appBarRef.addEventListener('mousedown', startDragging);
|
|
|
|
|
document.addEventListener('mousemove', dragSidebar);
|
|
|
|
|
document.addEventListener('mouseup', stopDragging);
|
|
|
|
|
document.addEventListener('mousemove', handleCursor);
|
|
|
|
|
}
|
2021-07-18 19:12:39 +03:00
|
|
|
hotkeys('A+1,A+2,A+3,A+4', function (event, handler) {
|
2021-05-31 11:28:46 +03:00
|
|
|
event.preventDefault();
|
|
|
|
|
switch (handler.key) {
|
2021-07-18 19:12:39 +03:00
|
|
|
case 'A+1':
|
2021-05-31 11:28:46 +03:00
|
|
|
handleAppClick(APPS_CONSTANTS.APPS.LIVE_CHAT);
|
|
|
|
|
break;
|
2021-07-18 19:12:39 +03:00
|
|
|
case 'A+2':
|
2021-05-31 11:28:46 +03:00
|
|
|
handleAppClick(APPS_CONSTANTS.APPS.QANDA);
|
|
|
|
|
break;
|
2021-07-18 19:12:39 +03:00
|
|
|
case 'A+3':
|
2021-05-31 11:28:46 +03:00
|
|
|
handleAppClick(APPS_CONSTANTS.APPS.NOTES);
|
|
|
|
|
break;
|
2021-07-18 19:12:39 +03:00
|
|
|
case 'A+4':
|
2021-05-31 11:28:46 +03:00
|
|
|
handleAppClick(APPS_CONSTANTS.APPS.POLL);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
2023-10-03 14:51:02 +00:00
|
|
|
|
|
|
|
|
onDestroy(() => {
|
2023-10-04 08:18:33 +01:00
|
|
|
if (getResizableSidebar()) {
|
2023-10-03 14:51:02 +00:00
|
|
|
appBarRef.removeEventListener('mousedown', startDragging);
|
|
|
|
|
document.removeEventListener('mousemove', dragSidebar);
|
|
|
|
|
document.removeEventListener('mouseup', stopDragging);
|
|
|
|
|
document.removeEventListener('mousemove', handleCursor);
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-10-06 12:49:40 +00:00
|
|
|
$: updateTopPadding($apps.isStudent);
|
2023-10-04 08:18:33 +01:00
|
|
|
$: getResizableSidebar();
|
2021-05-22 22:25:33 +03:00
|
|
|
</script>
|
|
|
|
|
|
2023-10-03 14:51:02 +00:00
|
|
|
<div
|
2023-10-06 12:49:40 +00:00
|
|
|
style={`--top-padding:${topPadding}`}
|
2023-10-04 08:18:33 +01:00
|
|
|
class={`${$apps.open ? 'open dark:bg-black' : 'close dark:bg-black'} root`}
|
2023-10-03 14:51:02 +00:00
|
|
|
bind:this={appBarRef}
|
|
|
|
|
>
|
2023-10-04 08:18:33 +01:00
|
|
|
<div class="apps">
|
2023-09-14 20:59:51 +00:00
|
|
|
<div class="lg:hidden">
|
|
|
|
|
<IconButton
|
|
|
|
|
buttonClassName="lg:hidden"
|
|
|
|
|
toolTipProps={{ title: 'Settings', hotkeys: ['A', '0'] }}
|
|
|
|
|
onClick={() => {
|
2023-10-04 08:18:33 +01:00
|
|
|
handleAppClick();
|
2023-09-14 20:59:51 +00:00
|
|
|
$apps.dropdown = !$apps.dropdown;
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Settings size={24} class="carbon-icon dark:text-white lg:hidden" />
|
|
|
|
|
</IconButton>
|
|
|
|
|
</div>
|
|
|
|
|
|
2021-05-31 11:28:46 +03:00
|
|
|
<IconButton
|
2021-07-18 19:12:39 +03:00
|
|
|
toolTipProps={{ title: 'Live Chat', hotkeys: ['A', '1'] }}
|
2021-05-31 11:28:46 +03:00
|
|
|
value={APPS_CONSTANTS.APPS.LIVE_CHAT}
|
|
|
|
|
onClick={handleAppClick}
|
2023-10-06 12:49:40 +00:00
|
|
|
selected={APPS_CONSTANTS.APPS.LIVE_CHAT === $apps.selectedApp}
|
2021-06-26 21:32:42 +03:00
|
|
|
>
|
2023-08-04 12:41:12 +01:00
|
|
|
<SendAlt size={24} class="carbon-icon dark:text-white" />
|
2021-05-31 11:28:46 +03:00
|
|
|
</IconButton>
|
|
|
|
|
|
|
|
|
|
<IconButton
|
2021-07-18 19:12:39 +03:00
|
|
|
toolTipProps={{ title: 'QandA', hotkeys: ['A', '2'] }}
|
2021-05-31 11:28:46 +03:00
|
|
|
value={APPS_CONSTANTS.APPS.QANDA}
|
|
|
|
|
onClick={handleAppClick}
|
2023-10-06 12:49:40 +00:00
|
|
|
selected={APPS_CONSTANTS.APPS.QANDA === $apps.selectedApp}
|
2021-06-26 21:32:42 +03:00
|
|
|
>
|
2023-08-04 12:41:12 +01:00
|
|
|
<Forum size={24} class="carbon-icon dark:text-white" />
|
2021-05-31 11:28:46 +03:00
|
|
|
</IconButton>
|
|
|
|
|
|
|
|
|
|
<IconButton
|
2021-07-18 19:12:39 +03:00
|
|
|
toolTipProps={{ title: 'Notes', hotkeys: ['A', '3'] }}
|
2021-05-31 11:28:46 +03:00
|
|
|
value={APPS_CONSTANTS.APPS.NOTES}
|
|
|
|
|
onClick={handleAppClick}
|
2023-10-06 12:49:40 +00:00
|
|
|
selected={APPS_CONSTANTS.APPS.NOTES === $apps.selectedApp}
|
2021-06-26 21:32:42 +03:00
|
|
|
>
|
2023-08-04 12:41:12 +01:00
|
|
|
<AlignBoxTopLeft size={24} class="carbon-icon dark:text-white" />
|
2021-05-31 11:28:46 +03:00
|
|
|
</IconButton>
|
|
|
|
|
|
|
|
|
|
<IconButton
|
2021-07-18 19:12:39 +03:00
|
|
|
toolTipProps={{ title: 'Poll', hotkeys: ['A', '4'] }}
|
2021-05-31 11:28:46 +03:00
|
|
|
value={APPS_CONSTANTS.APPS.POLL}
|
|
|
|
|
onClick={handleAppClick}
|
2023-10-06 12:49:40 +00:00
|
|
|
selected={APPS_CONSTANTS.APPS.POLL === $apps.selectedApp}
|
2021-06-26 21:32:42 +03:00
|
|
|
>
|
2023-08-04 12:41:12 +01:00
|
|
|
<ChartPie size={24} class="carbon-icon dark:text-white" />
|
2021-05-31 11:28:46 +03:00
|
|
|
</IconButton>
|
|
|
|
|
</div>
|
|
|
|
|
|
2023-10-06 12:49:40 +00:00
|
|
|
{#if !!$apps.selectedApp}
|
2023-10-03 14:51:02 +00:00
|
|
|
<div
|
|
|
|
|
class={`app cursor-auto lg:cursor-ew-resize ${
|
|
|
|
|
resize && ' border-l-8 border-l-blue-500 transition-none'
|
|
|
|
|
} `}
|
|
|
|
|
bind:this={appContentRef}
|
|
|
|
|
>
|
2023-10-06 12:49:40 +00:00
|
|
|
{#if $apps.selectedApp === APPS_CONSTANTS.APPS.QANDA}
|
2021-05-31 11:28:46 +03:00
|
|
|
<QandA {handleClose} />
|
2023-10-06 12:49:40 +00:00
|
|
|
{:else if $apps.selectedApp === APPS_CONSTANTS.APPS.LIVE_CHAT}
|
2021-05-31 11:28:46 +03:00
|
|
|
<LiveChat {handleClose} />
|
2023-10-06 12:49:40 +00:00
|
|
|
{:else if $apps.selectedApp === APPS_CONSTANTS.APPS.POLL}
|
2021-05-31 11:28:46 +03:00
|
|
|
<Poll {handleClose} />
|
2023-10-06 12:49:40 +00:00
|
|
|
{:else if $apps.selectedApp === APPS_CONSTANTS.APPS.NOTES}
|
2021-05-31 11:28:46 +03:00
|
|
|
<Notes {handleClose} />
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
2021-06-26 21:32:42 +03:00
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
.root {
|
2023-09-14 20:59:51 +00:00
|
|
|
height: calc(100vh - 48px);
|
2021-06-26 21:32:42 +03:00
|
|
|
position: sticky;
|
|
|
|
|
top: 0;
|
|
|
|
|
border-left: 1px solid var(--border-color);
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
|
|
|
|
& .apps {
|
|
|
|
|
padding-top: 20px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
width: 60px;
|
|
|
|
|
border-right: 1px solid var(--border-color);
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
& .app {
|
2023-10-03 14:51:02 +00:00
|
|
|
width: 100%;
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (min-width: 768px) and (max-width: 1023px) {
|
|
|
|
|
.app {
|
|
|
|
|
min-width: 280px;
|
|
|
|
|
max-width: 300px;
|
|
|
|
|
width: 300px;
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: 767px) {
|
|
|
|
|
.app {
|
|
|
|
|
width: 100%;
|
2021-06-26 21:32:42 +03:00
|
|
|
position: relative;
|
2021-07-05 10:52:20 +00:00
|
|
|
overflow: auto;
|
2021-06-26 21:32:42 +03:00
|
|
|
}
|
|
|
|
|
}
|
2023-09-14 20:59:51 +00:00
|
|
|
|
2023-09-24 13:20:04 +00:00
|
|
|
@media screen and (max-width: 1023px) {
|
2023-09-14 20:59:51 +00:00
|
|
|
.root {
|
|
|
|
|
position: absolute;
|
2023-10-06 12:49:40 +00:00
|
|
|
height: calc(100vh - var(--top-padding));
|
|
|
|
|
top: var(--top-padding);
|
2023-09-14 20:59:51 +00:00
|
|
|
right: 0;
|
|
|
|
|
z-index: 999;
|
|
|
|
|
}
|
|
|
|
|
.open {
|
|
|
|
|
position: absolute;
|
|
|
|
|
transform: translateX(0);
|
2023-10-06 12:49:40 +00:00
|
|
|
|
2023-09-14 20:59:51 +00:00
|
|
|
transition: all 0.2s ease-in-out;
|
|
|
|
|
}
|
|
|
|
|
.close {
|
|
|
|
|
position: absolute;
|
|
|
|
|
transform: translateX(100%);
|
|
|
|
|
display: none;
|
|
|
|
|
transition: all 0.2s ease-in-out;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-09-24 13:20:04 +00:00
|
|
|
|
|
|
|
|
@media screen and (min-width: 1024px) {
|
|
|
|
|
.root {
|
|
|
|
|
height: calc(100vh - 48px);
|
|
|
|
|
position: sticky;
|
|
|
|
|
top: 0;
|
|
|
|
|
border-left: 1px solid var(--border-color);
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
|
|
|
|
& .apps {
|
|
|
|
|
padding-top: 20px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
width: 60px;
|
|
|
|
|
border-right: 1px solid var(--border-color);
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
& .app {
|
2023-10-03 14:51:02 +00:00
|
|
|
width: 100%;
|
2023-09-24 13:20:04 +00:00
|
|
|
position: relative;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-26 21:32:42 +03:00
|
|
|
</style>
|