CLASSROOMIO-T-80: Replace sapper with sveltekit

This commit is contained in:
Rotimi Best
2023-08-02 19:35:27 +01:00
parent 8ffdf319b3
commit 7dfbb05451
320 changed files with 5207 additions and 18330 deletions
-86
View File
@@ -1,86 +0,0 @@
import { timestamp, files, shell } from '@sapper/service-worker';
const ASSETS = `cache${timestamp}`;
// `shell` is an array of all the files generated by the bundler,
// `files` is an array of everything in the `static` directory
const to_cache = shell.concat(files);
const staticAssets = new Set(to_cache);
self.addEventListener('install', event => {
event.waitUntil(
caches
.open(ASSETS)
.then(cache => cache.addAll(to_cache))
.then(() => {
self.skipWaiting();
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(async keys => {
// delete old caches
for (const key of keys) {
if (key !== ASSETS) await caches.delete(key);
}
self.clients.claim();
})
);
});
/**
* Fetch the asset from the network and store it in the cache.
* Fall back to the cache if the user is offline.
*/
async function fetchAndCache(request) {
const cache = await caches.open(`offline${timestamp}`)
try {
const response = await fetch(request);
cache.put(request, response.clone());
return response;
} catch (err) {
const response = await cache.match(request);
if (response) return response;
throw err;
}
}
self.addEventListener('fetch', event => {
if (event.request.method !== 'GET' || event.request.headers.has('range')) return;
const url = new URL(event.request.url);
// don't try to handle e.g. data: URIs
const isHttp = url.protocol.startsWith('http');
const isDevServerRequest = url.hostname === self.location.hostname && url.port !== self.location.port;
const isStaticAsset = url.host === self.location.host && staticAssets.has(url.pathname);
const skipBecauseUncached = event.request.cache === 'only-if-cached' && !isStaticAsset;
if (isHttp && !isDevServerRequest && !skipBecauseUncached) {
event.respondWith(
(async () => {
// always serve static files and bundler-generated assets from cache.
// if your application has other URLs with data that will never change,
// set this variable to true for them and they will only be fetched once.
const cachedAsset = isStaticAsset && await caches.match(event.request);
// for pages, you might want to serve a shell `service-worker-index.html` file,
// which Sapper has generated for you. It's not right for every
// app, but if it's right for yours then uncomment this section
/*
if (!cachedAsset && url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
return caches.match('/service-worker-index.html');
}
*/
return cachedAsset || fetchAndCache(event.request);
})()
);
}
});
+33
View File
@@ -0,0 +1,33 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="theme-color" content="#333333">
<!-- <link rel="stylesheet" href="global.css"> -->
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
<link rel="icon" type="image/png" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/logo-32.png">
<link href="/css/quill.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.plyr.io/3.7.3/plyr.css" />
<!--Crisp Chat
<script
type="text/javascript">window.$crisp = []; window.CRISP_WEBSITE_ID = "2158dbf9-90d4-4e50-b962-e1d8a1a6deb7"; (function () { d = document; s = d.createElement("script"); s.src = "https://client.crisp.chat/l.js"; s.async = 1; d.getElementsByTagName("head")[0].appendChild(s); })();</script>
-->
<script src="https://cdn.plyr.io/3.7.3/plyr.js">
</script>
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">
%sveltekit.body%
</div>
</body>
</html>
+97
View File
@@ -0,0 +1,97 @@
/*Write your global styles here, in PostCSS syntax */
@tailwind base;
@tailwind base;
@tailwind components;
@tailwind utilities;
/** Global scrollbar styles */
html {
--scrollbarBG: #fff;
--thumbBG: #ccc;
scroll-behavior: smooth;
}
#calendar .grid {
--sc-theme-calendar-colors-background-highlight: var(--main-primary-color);
}
* {
scrollbar-width: thin;
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
}
*::-webkit-scrollbar {
width: 10px;
height: 10px;
}
*::-webkit-scrollbar-track {
background: var(--scrollbarBG);
}
*::-webkit-scrollbar-thumb {
background-color: var(--thumbBG);
border-radius: 10px;
border: 2px solid var(--scrollbarBG);
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: revert;
font-weight: revert;
margin: 0.8em 0;
}
.prose h1,
.prose h2,
.prose h3,
.prose h4,
.prose h5,
.prose h6 {
margin-top: 0px !important;
margin-bottom: 16px !important;
font-weight: 600 !important;
line-height: 1.25 !important;
}
.dark .prose h1,
.dark .prose h2,
.dark .prose h3,
.dark .prose h4,
.dark .prose h5,
.dark .prose h6,
.dark .prose p {
color: #fff;
}
code {
white-space: pre-wrap;
}
[aria-current] :global(svg.carbon-icon),
.active :global(svg.carbon-icon) {
fill: var(--main-primary-color);
}
.prose a {
color: var(--main-primary-color);
}
.success :global(svg.carbon-icon) {
fill: green;
}
:global(svg.carbon-icon.error) {
fill: red;
}
.dark :global(svg.carbon-icon) {
fill: #fff;
}
@tailwind components;
@tailwind utilities;
-28
View File
@@ -1,28 +0,0 @@
import * as sapper from '@sapper/app';
import * as Sentry from '@sentry/browser';
import { Integrations } from '@sentry/tracing';
import { CaptureConsole } from '@sentry/integrations';
import config from './config';
console.log(`isProd`, config.isProd);
if (config.isProd) {
Sentry.init({
dsn: 'https://c966f7e8cb1d4306be20b26bb4f0cc96@o476906.ingest.sentry.io/5999999',
integrations: [
new Integrations.BrowserTracing(),
new CaptureConsole({
levels: ['error'],
}),
],
environment: config.isProd ? 'production' : 'development',
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 1.0,
});
}
sapper.start({
target: document.querySelector('#sapper'),
});
-18
View File
@@ -1,18 +0,0 @@
<script>
import Close24 from 'carbon-icons-svelte/lib/Close24';
import Close16 from 'carbon-icons-svelte/lib/Close16';
import IconButton from '../../IconButton/index.svelte';
export let onClick;
export let contained;
export let color = '';
export let size = 'large';
</script>
<IconButton {onClick} {color} {contained} {size}>
{#if size === 'large'}
<Close24 class="carbon-icon" title="Delete" />
{:else}
<Close16 class="carbon-icon" title="Delete" />
{/if}
</IconButton>
@@ -1,10 +0,0 @@
<script>
import Close24 from "carbon-icons-svelte/lib/Close24";
import IconButton from "../../../IconButton/index.svelte";
export let onClick;
</script>
<IconButton {onClick}>
<Close24 class="carbon-icon" title="Close" />
</IconButton>
-10
View File
@@ -1,10 +0,0 @@
<script>
import SendFilled24 from "carbon-icons-svelte/lib/SendFilled24";
import IconButton from "../../IconButton/index.svelte";
export let onClick;
</script>
<IconButton {onClick}>
<SendFilled24 class="carbon-icon" />
</IconButton>
-19
View File
@@ -1,19 +0,0 @@
<script>
export let className;
export let value;
export let size;
</script>
<p
class="{className} {size === 'sm'
? 'py-1 px-1'
: 'py-2 px-2'} org-avatar bg-gray-200 rounded-md text-center"
>
{value}
</p>
<style>
.org-avatar {
width: fit-content;
}
</style>
-96
View File
@@ -1,96 +0,0 @@
<style global lang="scss">
@tailwind base;
@tailwind components;
@tailwind utilities;
/** Global scrollbar styles */
html {
--scrollbarBG: #fff;
--thumbBG: #ccc;
scroll-behavior: smooth;
}
#calendar .grid {
--sc-theme-calendar-colors-background-highlight: var(--main-primary-color);
}
* {
scrollbar-width: thin;
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
}
*::-webkit-scrollbar {
width: 10px;
height: 10px;
}
*::-webkit-scrollbar-track {
background: var(--scrollbarBG);
}
*::-webkit-scrollbar-thumb {
background-color: var(--thumbBG);
border-radius: 10px;
border: 2px solid var(--scrollbarBG);
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: revert;
font-weight: revert;
margin: 0.8em 0;
}
.prose {
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 0px !important;
margin-bottom: 16px !important;
font-weight: 600 !important;
line-height: 1.25 !important;
}
}
.dark .prose {
h1,
h2,
h3,
h4,
h5,
h6,
p {
color: #fff;
}
}
code {
white-space: pre-wrap;
}
[aria-current] :global(svg.carbon-icon),
.active :global(svg.carbon-icon) {
fill: var(--main-primary-color);
}
.prose a {
color: var(--main-primary-color);
}
.success :global(svg.carbon-icon) {
fill: green;
}
:global(svg.carbon-icon.error) {
fill: red;
}
.dark :global(svg.carbon-icon) {
fill: #fff;
}
</style>
-1
View File
@@ -1,5 +1,4 @@
export default {
isProd: process.env.NODE_ENV !== 'development',
supabaseConfig: {
bucketPath:
'https://koxqonvbkeakwvmdegcf.supabase.in/storage/v1/object/sign/',
+29
View File
@@ -0,0 +1,29 @@
<script>
import ErrorIcon from '$lib/components/Icons/ErrorIcon.svelte';
</script>
<div
class="error-container m-auto flex flex-col-reverse lg:flex-row md:flex-col-reverse items-center justify-center h-screen w-screen py-10 dark:bg-gray-800">
<div class="md:w-full p-2 lg:w-2/4">
<h2 class="w-full text-lg lg:text-3xl font-medium lg:font-normal">
Something unexpected occured.
</h2>
<p class="dark:text-white w-full text-base font-normal my-6 text-gray-600">
Don't worry, your learning is safe. It isn't your fault, it is ours. We
have gotten the error notification and will push a fix ASAP. In the
meantime, take a short break and come back a bit later.
</p>
<a class="bg-blue-700 hover:bg-blue-900 hover:no-underline transition-all py-3 px-9 rounded-xl text-white mt-3"
href="mailto:support@classroomio.com">Contact Us</a>
</div>
<div class="w-72 lg:w-2/4 flex items-center justify-center">
<ErrorIcon />
</div>
</div>
<style>
.error-container {
max-width: 964px;
}
</style>
@@ -1,9 +1,9 @@
<script>
import marked from 'marked';
import PageNav from '../../../PageNav/index.svelte';
import CloseButton from '../../../Buttons/Close/index.svelte';
import TextField from '../../../Form/TextField.svelte';
// import SendButton from "../../../Buttons/Send/index.svelte";
import { marked } from 'marked';
import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from '$lib/components/Buttons/Close/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
// import SendButton from "$lib/components/Buttons/Send/index.svelte";
export let handleClose;
@@ -1,6 +1,6 @@
<script>
import PageNav from "../../../PageNav/index.svelte";
import CloseButton from "../../../Buttons/Close/index.svelte";
import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from '$lib/components/Buttons/Close/index.svelte';
export let handleClose;
</script>
@@ -1,20 +1,20 @@
<script>
import FormSection from "./FormSection.svelte";
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
import { VARIANTS } from "../../../../PrimaryButton/constants";
import FormSection from './FormSection.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
export let title = "Poll";
export let title = 'Poll';
export let onSubmit;
export let onCancel;
let values = {
question: "",
author: "",
question: '',
author: '',
isPublic: false,
expiration: "",
expiration: '',
options: [
{
label: "",
label: '',
selectedBy: [],
},
],
@@ -26,7 +26,7 @@
options: [
...values.options,
{
label: "",
label: '',
selectedBy: [],
},
],
@@ -58,7 +58,7 @@
{#each values.options as option, index}
<FormSection
label={index === 0 && "Options"}
label={index === 0 && 'Options'}
bind:value={option.label}
handleLabelButton={handleAddOptions}
handleInputButton={handleRemoveOptions(index)}
@@ -1,8 +1,8 @@
<script>
import PageNav from '../../../PageNav/index.svelte';
import CloseButton from '../../../Buttons/Close/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import { VARIANTS } from '../../../PrimaryButton/constants';
import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from '$lib/components/Buttons/Close/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import CreatePollForm from './components/CreatePollForm.svelte';
import Poll from './components/Poll.svelte';
import Tabs from './components/Tabs.svelte';
@@ -1,10 +1,10 @@
<script>
import marked from 'marked';
import CheckmarkOutline20 from 'carbon-icons-svelte/lib/CheckmarkOutline20';
import PageNav from '../../../PageNav/index.svelte';
import CloseButton from '../../../Buttons/Close/index.svelte';
import Vote from '../../../Vote/index.svelte';
import TextField from '../../../Form/TextField.svelte';
import { marked } from 'marked';
import CheckmarkOutline from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from '$lib/components/Buttons/Close/index.svelte';
import Vote from '$lib/components/Vote/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
export let handleClose;
let bodyRef;
@@ -108,7 +108,7 @@
class={`${question.answered && 'active'}`}
on:click={handleMarkAnswered(question.id)}
>
<CheckmarkOutline20 class="carbon-icon" />
<CheckmarkOutline size={20} class="carbon-icon" />
</button>
</div>
{/each}
@@ -1,11 +1,11 @@
<script>
import { onMount } from 'svelte';
import hotkeys from 'hotkeys-js';
import Forum24 from 'carbon-icons-svelte/lib/Forum24';
import AlignBoxTopLeft24 from 'carbon-icons-svelte/lib/AlignBoxTopLeft24';
import SendAlt24 from 'carbon-icons-svelte/lib/SendAlt24';
import ChartPie24 from 'carbon-icons-svelte/lib/ChartPie24';
import IconButton from '../IconButton/index.svelte';
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';
import QandA from './components/QandA/index.svelte';
import LiveChat from './components/LiveChat/index.svelte';
@@ -56,7 +56,7 @@
onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.LIVE_CHAT === selectedApp}
>
<SendAlt24 class="carbon-icon" />
<SendAlt size={24} class="carbon-icon" />
</IconButton>
<IconButton
@@ -65,7 +65,7 @@
onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.QANDA === selectedApp}
>
<Forum24 class="carbon-icon" />
<Forum size={24} class="carbon-icon" />
</IconButton>
<IconButton
@@ -74,7 +74,7 @@
onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.NOTES === selectedApp}
>
<AlignBoxTopLeft24 class="carbon-icon" />
<AlignBoxTopLeft size={24} class="carbon-icon" />
</IconButton>
<IconButton
@@ -83,7 +83,7 @@
onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.POLL === selectedApp}
>
<ChartPie24 class="carbon-icon" />
<ChartPie size={24} class="carbon-icon" />
</IconButton>
</div>
@@ -1,6 +1,6 @@
<script>
import PrimaryButton from '../PrimaryButton/index.svelte';
import { VARIANTS } from '../PrimaryButton/constants';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import GoogleIconColored from '../Icons/GoogleIconColored.svelte';
export let supabase;
@@ -13,7 +13,7 @@
async function signInWithGoogle() {
try {
console.log('signInWithGoogle');
const { user, session, error } = await supabase.auth.signIn({
const { user, session, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
});
@@ -0,0 +1,17 @@
<script>
import CloseIcon from 'carbon-icons-svelte/lib/Close.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
export let onClick;
export let contained;
export let color = '';
export let size = 'large';
</script>
<IconButton {onClick} {color} {contained} {size}>
{#if size === 'large'}
<CloseIcon size={24} class="carbon-icon" title="Delete" />
{:else}
<CloseIcon size={24} class="carbon-icon" title="Delete" />
{/if}
</IconButton>
@@ -0,0 +1,10 @@
<script>
import Close from 'carbon-icons-svelte/lib/Close.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
export let onClick = () => {};
</script>
<IconButton {onClick}>
<Close size={24} class="carbon-icon" title="Close" />
</IconButton>
@@ -0,0 +1,10 @@
<script>
import SendFilled from 'carbon-icons-svelte/lib/SendFilled.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
export let onClick;
</script>
<IconButton {onClick}>
<SendFilled size={24} class="carbon-icon" />
</IconButton>
+21
View File
@@ -0,0 +1,21 @@
<script>
export let className = '';
export let value = '';
export let size = '';
</script>
<p
class="{className} {size === 'sm'
? 'py-1 px-1'
: 'py-2 px-2'} org-avatar {className.includes('bg-')
? ''
: 'bg-gray-200'} rounded-md text-center"
>
{value}
</p>
<style>
.org-avatar {
width: fit-content;
}
</style>
@@ -1,6 +1,6 @@
<script>
export let value;
export let className;
export let value = 0;
export let className = '';
</script>
<p class={className ? className : 'bg-set mt-2'}>{value}</p>
@@ -1,5 +1,5 @@
<script>
import marked from 'marked';
import { marked } from 'marked';
export let code = '';
</script>
@@ -1,5 +1,5 @@
<script>
import PageNav from "../../../../PageNav/index.svelte";
import PageNav from '$lib/components/PageNav/index.svelte';
</script>
<PageNav title="Attendance" />
@@ -4,14 +4,14 @@
RadioButton,
Toggle,
} from 'carbon-components-svelte';
import { goto } from '@sapper/app';
import { updateCourse } from '../../../../utils/services/courses';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import { goto } from '$app/navigation';
import { updateCourse } from '$lib/utils/services/courses';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import Professional from './certificates/Professional.svelte';
import Plain from './certificates/Plain.svelte';
import { course } from '../../store';
import { currentOrg } from '../../../../utils/store/org';
import { course } from '$lib/components/Course/store';
import { currentOrg } from '$lib/utils/store/org';
const studentNamePlaceholder = 'Name of student';
const themes = ['professional', 'plain'];
@@ -59,7 +59,7 @@
{#each themes as theme}
<div class="flex mr-3">
<RadioButton value={theme} size="sm" />
<img src={`./${theme}.svg`} alt="themes" />
<img src={`/${theme}.svg`} alt="themes" />
</div>
{/each}
</RadioButtonGroup>
@@ -1,9 +1,9 @@
<script>
import { Toggle } from 'carbon-components-svelte';
import Modal from '../../../Modal/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import TextField from '../../../Form/TextField.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import { issueCertificateModal, resetForm } from './store';
const onToggle = (e) => {
@@ -1,5 +1,5 @@
<script>
import { course } from '../../../store';
import { course } from '$lib/components/Course/store';
import UnlockedCertificate from './UnlockedCertificate.svelte';
import LockedCertificate from './LockedCertificate.svelte';
</script>
@@ -1,5 +1,5 @@
<script>
import { course } from '../../../store';
import { course } from '$lib/components/Course/store';
</script>
<section class="studentContainer flex items-center justify-center w-full">
@@ -1,8 +1,8 @@
<script>
import { course } from '../../../store';
import { currentOrg } from '../../../../../utils/store/org';
import { profile } from '../../../../../utils/store/user';
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
import { course } from '$lib/components/Course/store';
import { currentOrg } from '$lib/utils/store/org';
import { profile } from '$lib/utils/store/user';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
let isLoading = false;
@@ -1,8 +1,8 @@
<script>
import { course } from '../../../store';
import { currentOrg } from '../../../../../utils/store/org';
import { course } from '$lib/components/Course/store';
import { currentOrg } from '$lib/utils/store/org';
export let studentName;
export let studentName = '';
let borderwidth = 'border-4';
let bordercolor = 'border-pink-700';
let logo = './logo-512.png';
@@ -1,6 +1,6 @@
<script>
import { course } from '../../../store';
import { currentOrg } from '../../../../../utils/store/org';
import { course } from '$lib/components/Course/store';
import { currentOrg } from '$lib/utils/store/org';
export let studentName;
let borderwidth = 'border-l-8';
@@ -1,8 +1,8 @@
<script>
import Modal from '../../../../Modal/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '../../../../PrimaryButton/constants';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { deleteConfirmation } from '../store/exercise';
export let onDelete = () => {};
@@ -10,36 +10,34 @@
handleAnswerSelect,
addDynamicValue,
} from '../store/exercise';
import Delete24 from 'carbon-icons-svelte/lib/Delete24';
import AddFilled24 from 'carbon-icons-svelte/lib/AddFilled24';
import CheckmarkFilled24 from 'carbon-icons-svelte/lib/CheckmarkFilled24';
import CheckmarkOutline24 from 'carbon-icons-svelte/lib/CheckmarkOutline24';
// import Subtract24 from "carbon-icons-svelte/lib/Subtract24";
import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte';
import AddFilledIcon from 'carbon-icons-svelte/lib/AddFilled.svelte';
import CheckmarkFilledIcon from 'carbon-icons-svelte/lib/CheckmarkFilled.svelte';
import CheckmarkOutlineIcon from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
import TextField from '../../../../Form/TextField.svelte';
import Modal from '../../../../Modal/index.svelte';
import TextArea from '../../../../Form/TextArea.svelte';
import Checkbox from '../../../../Form/Checkbox.svelte';
import DateTime from '../../../../Form/DateTime.svelte';
import RadioItem from '../../../../Form/RadioItem.svelte';
import IconButton from '../../../../IconButton/index.svelte';
import ErrorMessage from '../../../../ErrorMessage/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
import EditContent from '../../../../EditContent/index.svelte';
import { VARIANTS } from '../../../../PrimaryButton/constants';
import Select from '../../../../Form/Select.svelte';
import QuestionContainer from '../../../../QuestionContainer/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import Checkbox from '$lib/components/Form/Checkbox.svelte';
import DateTime from '$lib/components/Form/DateTime.svelte';
import RadioItem from '$lib/components/Form/RadioItem.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
import ErrorMessage from '$lib/components/ErrorMessage/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import EditContent from '$lib/components/EditContent/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import Select from '$lib/components/Form/Select.svelte';
import QuestionContainer from '$lib/components/QuestionContainer/index.svelte';
import DeleteConfirmationModal from './DeleteConfirmation.svelte';
import OrderModal from './OrderModal.svelte';
import {
QUESTION_TYPE,
QUESTION_TYPES,
} from '../../../../Question/constants';
} from '$lib/components/Question/constants';
import { filterOutDeleted } from './functions';
import { deleteExercise } from '../../../../../utils/services/courses';
import { deleteExercise } from '$lib/utils/services/courses';
import { lesson } from '../store/lessons';
// import EditContent from "../../../../EditContent/index.svelte";
// import readme from "../../readme.js";
// import EditContent from "$lib/components/EditContent/index.svelte";
// let value = readme;
const extraActions = ['Code Snippets', 'Upload image'];
@@ -221,7 +219,7 @@
options={extraActions}
handleOptionClick={handleOptionClick(question.id)}
>
<AddFilled24 class="carbon-icon" />
<AddFilledIcon class="carbon-icon" />
<p class="dark:text-white ml-2 text-gray-600">Add</p>
</Dropdown> -->
@@ -245,7 +243,7 @@
value="write-code"
onClick={() => handleCode(question.id, false)}
>
<Delete24 class="carbon-icon" />
<TrashCanIcon size={24} class="carbon-icon" />
</IconButton>
</div>
{/if}
@@ -264,7 +262,7 @@
value={option.id}
onClick={handleRemoveOption(question.id, option.id)}
>
<Delete24 class="carbon-icon" />
<TrashCanIcon size={24} class="carbon-icon" />
</IconButton>
<IconButton
value={option.id}
@@ -272,9 +270,9 @@
buttonClassName={option.is_correct && 'success'}
>
{#if option.is_correct}
<CheckmarkFilled24 class="carbon-icon" />
<CheckmarkFilledIcon size={24} class="carbon-icon" />
{:else}
<CheckmarkOutline24 class="carbon-icon" />
<CheckmarkOutlineIcon size={24} class="carbon-icon" />
{/if}
</IconButton>
</div>
@@ -295,7 +293,7 @@
value={option.id}
onClick={handleRemoveOption(question.id, option.id)}
>
<Delete24 class="carbon-icon" />
<TrashCanIcon size={24} class="carbon-icon" />
</IconButton>
<IconButton
value={option.id}
@@ -303,9 +301,9 @@
buttonClassName={option.is_correct && 'success'}
>
{#if option.is_correct}
<CheckmarkFilled24 class="carbon-icon" />
<CheckmarkFilledIcon size={24} class="carbon-icon" />
{:else}
<CheckmarkOutline24 class="carbon-icon" />
<CheckmarkOutlineIcon size={24} class="carbon-icon" />
{/if}
</IconButton>
</div>
@@ -332,7 +330,7 @@
variant={VARIANTS.OUTLINED}
onClick={handleAddOption(question.id)}
>
<AddFilled24 class="carbon-icon" />
<AddFilledIcon size={24} class="carbon-icon" />
<p class="dark:text-white ml-2">Add option</p>
</PrimaryButton>
</div>
@@ -1,12 +1,12 @@
<script>
import { onMount } from 'svelte';
import Modal from '../../../../Modal/index.svelte';
import Select from '../../../../Form/Select.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
import { VARIANTS } from '../../../../PrimaryButton/constants';
import Modal from '$lib/components/Modal/index.svelte';
import Select from '$lib/components/Form/Select.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import Preview from './Preview.svelte';
import { SELECTABLE_STATUS } from './constants';
import { snackbarStore } from '../../../../Snackbar/store';
import { snackbarStore } from '$lib/components/Snackbar/store';
export let open = false;
export let onClose = () => {};
@@ -1,11 +1,11 @@
<script lang="ts">
import { dndzone } from 'svelte-dnd-action';
import CheckboxCheckedFilled16 from 'carbon-icons-svelte/lib/CheckboxCheckedFilled16';
import RadioButtonChecked16 from 'carbon-icons-svelte/lib/RadioButtonChecked16';
import TextAlignJustify16 from 'carbon-icons-svelte/lib/TextAlignJustify16';
import CheckboxCheckedFilledIcon from 'carbon-icons-svelte/lib/CheckboxCheckedFilled.svelte';
import RadioButtonCheckedIcon from 'carbon-icons-svelte/lib/RadioButtonChecked.svelte';
import TextAlignJustifyIcon from 'carbon-icons-svelte/lib/TextAlignJustify.svelte';
import { flip } from 'svelte/animate';
import Modal from '../../../../Modal/index.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import { questionnaireOrder, questionnaire } from '../store/exercise';
import { filterOutDeleted } from './functions';
@@ -77,11 +77,11 @@
class="flex items-center rounded-md p-4 border border-blue-600"
>
{#if item.type === 1}
<RadioButtonChecked16 class="carbon-icon active" />
<RadioButtonCheckedIcon size={16} class="carbon-icon active" />
{:else if item.type === 2}
<CheckboxCheckedFilled16 class="carbon-icon active" />
<CheckboxCheckedFilledIcon size={16} class="carbon-icon active" />
{:else}
<TextAlignJustify16 class="carbon-icon active" />
<TextAlignJustifyIcon size={16} class="carbon-icon active" />
{/if}
{` ${item.name}`}
</div>
@@ -1,8 +1,8 @@
<script>
import RadioQuestion from '../../../../Question/RadioQuestion/index.svelte';
import CheckboxQuestion from '../../../../Question/CheckboxQuestion/index.svelte';
import TextareaQuestion from '../../../../Question/TextareaQuestion/index.svelte';
import { QUESTION_TYPE } from '../../../../Question/constants';
import RadioQuestion from '$lib/components/Question/RadioQuestion/index.svelte';
import CheckboxQuestion from '$lib/components/Question/CheckboxQuestion/index.svelte';
import TextareaQuestion from '$lib/components/Question/TextareaQuestion/index.svelte';
import { QUESTION_TYPE } from '$lib/components/Question/constants';
import { getPropsForQuestion } from './functions';
export let questions = [];
@@ -1,24 +1,28 @@
<script>
import marked from 'marked';
import { marked } from 'marked';
import { fly } from 'svelte/transition';
import { group, course } from '../../../store';
import { group, course } from '$lib/components/Course/store';
import { questionnaire } from '../store/exercise';
import { questionnaireMetaData } from '../store/answers';
import Preview from './Preview.svelte';
import RadioQuestion from '../../../../Question/RadioQuestion/index.svelte';
import CheckboxQuestion from '../../../../Question/CheckboxQuestion/index.svelte';
import TextareaQuestion from '../../../../Question/TextareaQuestion/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
import RoleBasedSecurity from '../../../../RoleBasedSecurity/index.svelte';
import Progress from '../../../../Progress/index.svelte';
import { removeDuplicate } from '../../../../../utils/functions/removeDuplicate';
import { QUESTION_TYPE } from '../../../../Question/constants';
import RadioQuestion from '$lib/components/Question/RadioQuestion/index.svelte';
import CheckboxQuestion from '$lib/components/Question/CheckboxQuestion/index.svelte';
import TextareaQuestion from '$lib/components/Question/TextareaQuestion/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import Progress from '$lib/components/Progress/index.svelte';
import { removeDuplicate } from '$lib/utils/functions/removeDuplicate';
import { QUESTION_TYPE } from '$lib/components/Question/constants';
import { STATUS } from './constants';
import { getPropsForQuestion, filterOutDeleted } from './functions';
import { formatAnswers, getGroupMemberId } from '../../../function';
import { submitExercise } from '../../../../../utils/services/courses';
import { fetchSubmission } from '../../../../../utils/services/submissions';
import { profile } from '../../../../../utils/store/user';
import {
formatAnswers,
getGroupMemberId,
} from '$lib/components/Course/function';
import { submitExercise } from '$lib/utils/services/courses';
import { fetchSubmission } from '$lib/utils/services/submissions';
import { profile } from '$lib/utils/store/user';
export let preview;
export let exerciseId;
@@ -183,7 +187,7 @@
>
<h3 class="dark:text-white text-2xl">
No questions added. <br />
<RoleBasedSecurity allowedRoles="[1,2]">
<RoleBasedSecurity allowedRoles={[1, 2]}>
Click the <span class="text-blue-700">Edit</span> button to add.
</RoleBasedSecurity>
</h3>
@@ -1,5 +1,5 @@
import { QUESTION_TYPE } from '../../../../Question/constants';
import { toggleConfetti } from '../../../../Confetti/store';
import { QUESTION_TYPE } from '$lib/components/Question/constants';
import { toggleConfetti } from '$lib/components/Confetti/store';
export const isAnswerCorrect = (options, answer) => {
return options.some((option) => option.is_correct && option.value === answer);
@@ -1,11 +1,10 @@
<script>
import { onDestroy } from 'svelte';
import AddAlt32 from 'carbon-icons-svelte/lib/AddAlt32';
// import Delete32 from 'carbon-icons-svelte/lib/Delete32';
import Table32 from 'carbon-icons-svelte/lib/Table32';
import Settings32 from 'carbon-icons-svelte/lib/Settings32';
import View32 from 'carbon-icons-svelte/lib/View32';
import ViewFilled32 from 'carbon-icons-svelte/lib/ViewFilled32';
import AddAltIcon from 'carbon-icons-svelte/lib/AddAlt.svelte';
import TableIcon from 'carbon-icons-svelte/lib/Table.svelte';
import SettingsIcon from 'carbon-icons-svelte/lib/Settings.svelte';
import ViewIcon from 'carbon-icons-svelte/lib/View.svelte';
import ViewFilledIcon from 'carbon-icons-svelte/lib/ViewFilled.svelte';
import {
handleAddQuestion,
questionnaire,
@@ -13,15 +12,15 @@
reset,
questionnaireOrder,
} from '../store/exercise';
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
import PageBody from '../../../../PageBody/index.svelte';
import IconButton from '../../../../IconButton/index.svelte';
import RoleBasedSecurity from '../../../../RoleBasedSecurity/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import PageBody from '$lib/components/PageBody/index.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import ViewMode from './ViewMode.svelte';
import EditMode from './EditMode.svelte';
import MODES from '../../../../../utils/constants/mode.js';
import { VARIANTS } from '../../../../PrimaryButton/constants';
import { upsertExercise } from '../../../../../utils/services/courses';
import MODES from '$lib/utils/constants/mode.js';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { upsertExercise } from '$lib/utils/services/courses';
export let exerciseId;
export let refetchExercise = () => {};
@@ -71,7 +70,7 @@
<PageBody padding="px-4">
<svelte:fragment slot="header">
<div class="flex items-center">
<RoleBasedSecurity allowedRoles="[1,2]">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<PrimaryButton
className="mr-2"
variant={VARIANTS.CONTAINED}
@@ -96,9 +95,9 @@
contained={true}
>
{#if preview}
<ViewFilled32 class="carbon-icon" />
<ViewFilledIcon size={32} class="carbon-icon" />
{:else}
<View32 class="carbon-icon" />
<ViewIcon size={32} class="carbon-icon" />
{/if}
</IconButton>
{/if}
@@ -110,19 +109,19 @@
onClick={handleAddQuestion}
toolTipProps={{ title: 'Add question', direction: 'bottom' }}
>
<AddAlt32 class="carbon-icon" />
<AddAltIcon size={32} class="carbon-icon" />
</IconButton>
<IconButton
onClick={() => ($questionnaireOrder.open = true)}
toolTipProps={{ title: 'Order questionnaire', direction: 'bottom' }}
>
<Table32 class="carbon-icon" />
<TableIcon size={32} class="carbon-icon" />
</IconButton>
<IconButton
onClick={() => (editDescription = true)}
toolTipProps={{ title: 'Edit description', direction: 'bottom' }}
>
<Settings32 class="carbon-icon" />
<SettingsIcon size={32} class="carbon-icon" />
</IconButton>
<!-- <IconButton
@@ -1,19 +1,19 @@
<script>
import { goto } from '@sapper/app';
import { goto } from '$app/navigation';
import { onMount } from 'svelte';
import AudioConsole32 from 'carbon-icons-svelte/lib/AudioConsole32';
import Box from '../../../../Box/index.svelte';
import AudioConsoleIcon from 'carbon-icons-svelte/lib/AudioConsole.svelte';
import Box from '$lib/components/Box/index.svelte';
import { Moon } from 'svelte-loading-spinners';
import Backdrop from '../../../../Backdrop/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
import RoleBasedSecurity from '../../../../RoleBasedSecurity/index.svelte';
import PageBody from '../../../../PageBody/index.svelte';
import Modal from '../../../../Modal/index.svelte';
import TextField from '../../../../Form/TextField.svelte';
import Backdrop from '$lib/components/Backdrop/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import PageBody from '$lib/components/PageBody/index.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import Exercise from '../Exercise/index.svelte';
import { supabase } from '../../../../../utils/functions/supabase';
import { createExercise } from '../../../../../utils/services/courses';
import { QUESTION_TYPES } from '../../../../Question/constants';
import { supabase } from '$lib/utils/functions/supabase';
import { createExercise } from '$lib/utils/services/courses';
import { QUESTION_TYPES } from '$lib/components/Question/constants';
import { lesson } from '../store/lessons';
import { questionnaire, isQuestionnaireFetching } from '../store/exercise';
@@ -70,7 +70,7 @@
isFetching = true;
isQuestionnaireFetching.update(() => true);
const { data } = await supabase
let { data, error } = await supabase
.from('exercise')
.select(
`
@@ -85,6 +85,10 @@
.eq('id', exerciseId)
.single();
if (error) {
return;
}
if (data && Array.isArray(data.questions)) {
// Need to set the question type inorder for the select in the questionnaire builder to match
data.questions.forEach((question) => {
@@ -94,8 +98,10 @@
return question;
});
data.questions = data.questions.sort((a, b) => a.order - b.order);
} else {
} else if (data) {
data.questions = [];
} else {
data = {};
}
data.is_title_dirty = false;
@@ -156,7 +162,7 @@
<PageBody>
<slot:fragment slot="header">
<RoleBasedSecurity allowedRoles="[1,2]">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<PrimaryButton
className="mr-2"
label="Add"
@@ -176,7 +182,7 @@
</a>
{:else}
<Box>
<AudioConsole32 class="carbon-icon w-80" />
<AudioConsoleIcon size={32} class="carbon-icon w-80" />
<h3 class="text-3xl text-gray-500 dark:text-white">
No Exercise Added
</h3>
@@ -1,13 +1,13 @@
<script>
import MODES from '../../../../../utils/constants/mode.js';
import { formatYoutubeVideo } from '../../../../../utils/functions/formatYoutubeVideo';
import MODES from '$lib/utils/constants/mode.js';
import { formatYoutubeVideo } from '$lib/utils/functions/formatYoutubeVideo';
import Tabs from '../../../../Tabs/index.svelte';
import TabContent from '../../../../TabContent/index.svelte';
import MarkdownRender from '../../../../MarkdownRender/index.svelte';
import Box from '../../../../Box/index.svelte';
import EditContent from '../../../../EditContent/index.svelte';
import TextField from '../../../../Form/TextField.svelte';
import Tabs from '$lib/components/Tabs/index.svelte';
import TabContent from '$lib/components/TabContent/index.svelte';
import MarkdownRender from '$lib/components/MarkdownRender/index.svelte';
import Box from '$lib/components/Box/index.svelte';
import EditContent from '$lib/components/EditContent/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import {
lesson,
handleUpdateLessonMaterials,
@@ -2,9 +2,9 @@ import { writable } from 'svelte/store';
import {
QUESTION_TEMPLATE,
QUESTION_TYPE,
} from '../../../../Question/constants';
} from '$lib/components/Question/constants';
import { questionnaireMetaData } from './answers';
import { isUUID } from '../../../../../utils/functions/isUUID';
import { isUUID } from '$lib/utils/functions/isUUID';
export const isQuestionnaireFetching = writable(false);
export const deleteConfirmation = writable({ open: false });
@@ -1,11 +1,12 @@
import { writable, Writable, Updater } from 'svelte/store';
import { writable } from 'svelte/store';
import type { Writable, Updater } from 'svelte/store';
import {
createLesson,
updateLesson,
deleteLesson,
} from '../../../../../utils/services/courses';
} from '$lib/utils/services/courses';
import type { Lesson, Course } from '../../../../../utils/types';
import type { Lesson, Course } from '$lib/utils/types';
export const lessons: Writable<Lesson[]> = writable([]);
export const lesson = writable({
@@ -1,5 +1,5 @@
<script>
import CaretSortDown20 from 'carbon-icons-svelte/lib/CaretSortDown20';
import CaretSortDownIcon from 'carbon-icons-svelte/lib/CaretSortDown.svelte';
let isExpanded = true;
export let handleClick = () => {};
@@ -22,7 +22,8 @@
on:click={onClick}
>
{#if !hideSortIcon}
<CaretSortDown20
<CaretSortDownIcon
size={20}
class="carbon-icon-sort {isExpanded ? '' : 'carbon-icon-minimize'}"
/>
{/if}
@@ -1,39 +1,39 @@
<script>
import { onMount } from 'svelte';
import { stores, goto } from '@sapper/app';
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import hotkeys from 'hotkeys-js';
import Home32 from 'carbon-icons-svelte/lib/Home32';
import CheckmarkFilled20 from 'carbon-icons-svelte/lib/CheckmarkFilled20';
import Settings20 from 'carbon-icons-svelte/lib/Settings20';
import ChevronLeft16 from 'carbon-icons-svelte/lib/ChevronLeft16';
import ChevronRight16 from 'carbon-icons-svelte/lib/ChevronRight16';
import HomeIcon from 'carbon-icons-svelte/lib/Home.svelte';
import CheckmarkFilledIcon from 'carbon-icons-svelte/lib/CheckmarkFilled.svelte';
import SettingsIcon from 'carbon-icons-svelte/lib/Settings.svelte';
import ChevronLeftIcon from 'carbon-icons-svelte/lib/ChevronLeft.svelte';
import ChevronRightIcon from 'carbon-icons-svelte/lib/ChevronRight.svelte';
import NavExpandable from './NavExpandable.svelte';
import PageNav from '../../../PageNav/index.svelte';
import IconButton from '../../../IconButton/index.svelte';
import Avatar from '../../../Avatar/index.svelte';
import PageNav from '$lib/components/PageNav/index.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
import Avatar from '$lib/components/Avatar/index.svelte';
import {
getNavItemRoute,
getLessonsRoute,
getLectureNo,
} from '../../function';
} from '$lib/components/Course/function';
import RoleBasedSecurity from '../../../RoleBasedSecurity/index.svelte';
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import Settings from '../Settings/index.svelte';
import { settingsDialog } from '../Settings/store';
import { lessons } from '../Lesson/store/lessons';
import { course } from '../../store';
import { updateCourse } from '../../../../utils/services/courses';
import { profile } from '../../../../utils/store/user';
import { currentOrg, currentOrgPath } from '../../../../utils/store/org';
import { isMobile } from '../../../../utils/store/useMobile';
import { course } from '$lib/components/Course/store';
import { updateCourse } from '$lib/utils/services/courses';
import { profile } from '$lib/utils/store/user';
import { currentOrgPath } from '$lib/utils/store/org';
import { isMobile } from '$lib/utils/store/useMobile';
import { browser } from '$app/environment';
// export let lessonId;
export let path;
export let isStudent = null;
let show = null;
const { page } = stores();
function handleMainGroupClick(href) {
return () => {
if ($isMobile) {
@@ -47,7 +47,7 @@
function getHref(item) {
return item.to;
// return item.is_complete ? item.to : path || $page.path
// return item.is_complete ? item.to : path || $page.url.pathname
}
function handleSaveTitle() {
@@ -79,7 +79,7 @@
$: handleMobileChange($isMobile);
$: {
if (process.browser && show !== null) {
if (browser) {
localStorage.setItem('hideCourseNav', `${!show}`);
}
}
@@ -154,11 +154,11 @@
<Avatar src={$course.logo} />
</slot:fragment>
<slot:fragment slot="widget">
<RoleBasedSecurity allowedRoles="[1,2]">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<IconButton
onClick={() => ($settingsDialog.open = !$settingsDialog.open)}
>
<Settings20 class="carbon-icon" />
<SettingsIcon size={20} class="carbon-icon" />
</IconButton>
</RoleBasedSecurity>
</slot:fragment>
@@ -169,20 +169,20 @@
<NavExpandable
label={navItem.label}
handleClick={handleMainGroupClick(navItem.to)}
isGroupActive={(path || $page.path) === navItem.to}
isGroupActive={(path || $page.url.pathname) === navItem.to}
hideSortIcon={navItem.hideSortIcon}
>
{#if navItem.isLecture}
{#each $lessons as item, index}
<a
class="item flex items-center {(
path || $page.path
path || $page.url.pathname
).includes(item.id) && 'active'} pl-7 py-3 {isStudent &&
!item.is_complete
? 'cursor-not-allowed'
: ''}"
href={isStudent && !item.is_complete
? $page.path
? $page.url.pathname
: getLessonsRoute($course.id, item.id)}
on:click={() => {
if ($isMobile) {
@@ -196,7 +196,7 @@
<span>{item.title}</span>
{#if item.is_complete}
<span class="ml-2 success">
<CheckmarkFilled20 class="carbon-icon" />
<CheckmarkFilledIcon size={20} class="carbon-icon" />
</span>
{:else}
<span class="text-md ml-2">🔒</span>
@@ -217,7 +217,7 @@
onClick={() => goto(`${$currentOrgPath}/courses`)}
buttonClassName="mx-3"
>
<Home32 class="carbon-icon" />
<HomeIcon size={32} class="carbon-icon" />
</IconButton>
<a class="block mx-3" href={`/profile/${$profile.id}`}>
<Avatar src={$profile.avatar_url} name={$profile.username} />
@@ -240,9 +240,9 @@
}}
>
{#if show}
<ChevronLeft16 />
<ChevronLeftIcon size={16} />
{:else}
<ChevronRight16 />
<ChevronRightIcon size={16} />
{/if}
</IconButton>
</div>
@@ -1,8 +1,8 @@
<script>
import Modal from '../../../Modal/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '../../../PrimaryButton/constants';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { deleteMemberModal } from './store';
export let email;
@@ -1,15 +1,12 @@
<script>
import Modal from '../../../Modal/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import { ROLE } from '../../../../utils/constants/roles';
import {
addGroupMember,
fetchGroup,
} from '../../../../utils/services/courses';
import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import { ROLE } from '$lib/utils/constants/roles';
import { addGroupMember, fetchGroup } from '$lib/utils/services/courses';
import { invitationModal, resetForm } from './store';
import { validateForm } from '../../../Courses/functions';
import { course, setCourse } from '../../store';
import { validateForm } from '$lib/components/Courses/functions';
import { course, setCourse } from '$lib/components/Course/store';
let errors = {
emails: '',
@@ -1,18 +1,15 @@
<script>
import { goto } from '@sapper/app';
import Modal from '../../../Modal/index.svelte';
import TextField from '../../../Form/TextField.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import UploadImage from '../../../UploadImage/index.svelte';
import { goto } from '$app/navigation';
import Modal from '$lib/components/Modal/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import UploadImage from '$lib/components/UploadImage/index.svelte';
import { VARIANTS } from '../../../PrimaryButton/constants';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { settingsDialog } from './store';
import { course } from '../../store';
import {
updateCourse,
deleteCourse,
} from '../../../../utils/services/courses';
import { course } from '$lib/components/Course/store';
import { updateCourse, deleteCourse } from '$lib/utils/services/courses';
let shouldDelete = false;
let avatar;
@@ -1,13 +1,13 @@
<script>
import marked from 'marked';
import { marked } from 'marked';
import RoleBasedSecurity from '../RoleBasedSecurity/index.svelte';
import PageNav from '../PageNav/index.svelte';
import MODES from '../../utils/constants/mode';
import PrimaryButton from '../PrimaryButton/index.svelte';
import MODES from '$lib/utils/constants/mode';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import PageBody from '../PageBody/index.svelte';
import EditContent from '../EditContent/index.svelte';
import { course } from './store';
import { updateCourse } from '../../utils/services/courses';
import { updateCourse } from '$lib/utils/services/courses';
let mode = MODES.view;
let isDirty = false;
@@ -27,7 +27,7 @@
<PageNav title="Overview" disableSticky={true}>
<svelte:fragment slot="widget">
<RoleBasedSecurity allowedRoles="[1,2]">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="flex items-center">
<PrimaryButton
className="mr-2"
@@ -1,8 +1,9 @@
import { writable, Writable } from 'svelte/store';
import { writable } from 'svelte/store';
import type { Writable } from 'svelte/store';
import { lessons } from './components/Lesson/store/lessons';
//@ts-ignore
import { ROLE } from '../../utils/constants/roles';
import type { Course } from '../../utils/types';
import { ROLE } from '$lib/utils/constants/roles';
import type { Course } from '$lib/utils/types';
export const course: Writable<Course> = writable({
id: '',
@@ -1,14 +1,14 @@
<script>
import { Moon } from 'svelte-loading-spinners';
import Navigation from '../Course/components/Navigation/index.svelte';
import Backdrop from '../../components/Backdrop/index.svelte';
import Backdrop from '$lib/components/Backdrop/index.svelte';
// import { lessons, lesson } from '../Course/components/Lesson/store/lessons';
// import { questionnaire } from '../Course/components/Lesson/Exercise/store/exercise';
// import { questionnaireMetaData } from '../Course/components/Lesson/store/answers';
import { course, group } from '../Course/store';
import Confetti from '../Confetti/index.svelte';
import { isMobile } from '../../utils/store/useMobile';
import { profile } from '../../utils/store/user';
import { isMobile } from '$lib/utils/store/useMobile';
import { profile } from '$lib/utils/store/user';
export let path = '';
export let isExercisePage = false;
@@ -1,8 +1,8 @@
<script>
import ChevronLeft16 from 'carbon-icons-svelte/lib/ChevronLeft16';
import ChevronRight16 from 'carbon-icons-svelte/lib/ChevronRight16';
import { isMobile } from '../../../../utils/store/useMobile';
import IconButton from '../../../IconButton/index.svelte';
import ChevronLeftIcon from 'carbon-icons-svelte/lib/ChevronLeft.svelte';
import ChevronRightIcon from 'carbon-icons-svelte/lib/ChevronRight.svelte';
import { isMobile } from '$lib/utils/store/useMobile';
import IconButton from '$lib/components/IconButton/index.svelte';
export let show = true;
</script>
@@ -31,9 +31,9 @@
}}
>
{#if show}
<ChevronLeft16 />
<ChevronLeftIcon size={16} />
{:else}
<ChevronRight16 />
<ChevronRightIcon size={16} />
{/if}
</IconButton>
</div>
@@ -2,7 +2,7 @@
import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set';
import get from 'lodash/get';
import TextEditor from '../../../TextEditor/index.svelte';
import TextEditor from '$lib/components/TextEditor/index.svelte';
export let course;
</script>
@@ -2,7 +2,7 @@
import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set';
import get from 'lodash/get';
import TextEditor from '../../../TextEditor/index.svelte';
import TextEditor from '$lib/components/TextEditor/index.svelte';
export let course;
</script>
@@ -1,6 +1,6 @@
<script>
import TextArea from '../../../Form/TextArea.svelte';
import TextField from '../../../Form/TextField.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
export let course = {};
</script>
@@ -3,10 +3,10 @@
import set from 'lodash/set';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import TextArea from '../../../Form/TextArea.svelte';
import TextField from '../../../Form/TextField.svelte';
import UploadImage from '../../../UploadImage/index.svelte';
import { uploadAvatar } from '../../../../utils/services/courses';
import TextArea from '$lib/components/Form/TextArea.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import UploadImage from '$lib/components/UploadImage/index.svelte';
import { uploadAvatar } from '$lib/utils/services/courses';
export let course = {};
let name;
@@ -4,8 +4,8 @@
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import { Toggle } from 'carbon-components-svelte';
import TextEditor from '../../../TextEditor/index.svelte';
import TextField from '../../../Form/TextField.svelte';
import TextEditor from '$lib/components/TextEditor/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
export let course = {};
@@ -2,7 +2,7 @@
import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set';
import get from 'lodash/get';
import TextEditor from '../../../TextEditor/index.svelte';
import TextEditor from '$lib/components/TextEditor/index.svelte';
export let course;
</script>
@@ -1,12 +1,12 @@
<script>
import Save24 from 'carbon-icons-svelte/lib/Save24';
import Delete24 from 'carbon-icons-svelte/lib/Delete24';
import SaveIcon from 'carbon-icons-svelte/lib/Save.svelte';
import DeleteIcon from 'carbon-icons-svelte/lib/Delete.svelte';
import { Toggle } from 'carbon-components-svelte';
import IconButton from '../../../IconButton/index.svelte';
import UploadImage from '../../../UploadImage/index.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import TextField from '../../../Form/TextField.svelte';
import { uploadAvatar } from '../../../../utils/services/courses';
import IconButton from '$lib/components/IconButton/index.svelte';
import UploadImage from '$lib/components/UploadImage/index.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import { uploadAvatar } from '$lib/utils/services/courses';
export let courseId;
export let reviews = [];
@@ -86,7 +86,7 @@
onClick={deleteReviewData}
size="large"
>
<Delete24 class="carbon-icon" />
<DeleteIcon size={24} class="carbon-icon" />
</IconButton>
<IconButton
contained={true}
@@ -94,7 +94,7 @@
onClick={() => onExpand(review.id)}
size="large"
>
<Save24 class="carbon-icon" />
<SaveIcon size={24} class="carbon-icon" />
</IconButton>
</div>
</div>
@@ -3,14 +3,14 @@
import get from 'lodash/get';
import set from 'lodash/set';
import z from 'zod';
import ChevronDown16 from 'carbon-icons-svelte/lib/ChevronDown16';
import IconButton from '../../../IconButton/index.svelte';
import { isMobile } from '../../../../utils/store/useMobile';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import { VARIANTS } from '../../../PrimaryButton/constants';
import ChevronDownIcon from 'carbon-icons-svelte/lib/ChevronDown.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
import { isMobile } from '$lib/utils/store/useMobile';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import ReviewFormEditor from './ReviewFormEditor.svelte';
import Avatar from '../../../Avatar/index.svelte';
import { processErrors } from '../../../../utils/functions/validator';
import Avatar from '$lib/components/Avatar/index.svelte';
import { processErrors } from '$lib/utils/functions/validator';
export let course = {};
@@ -116,7 +116,7 @@
onClick={() => onExpand(review.id)}
size={$isMobile ? 'large' : 'small'}
>
<ChevronDown16 class="carbon-icon" />
<ChevronDownIcon size={16} class="carbon-icon" />
</IconButton>
</div>
{/if}
@@ -1,12 +1,12 @@
<script>
import { goto } from '@sapper/app';
import ChevronRight24 from 'carbon-icons-svelte/lib/ChevronRight24';
import ArrowLeft24 from 'carbon-icons-svelte/lib/ArrowLeft24';
import ArrowUpRight24 from 'carbon-icons-svelte/lib/ArrowUpRight24';
import { goto } from '$app/navigation';
import ChevronRightIcon from 'carbon-icons-svelte/lib/ChevronRight.svelte';
import ArrowLeftIcon from 'carbon-icons-svelte/lib/ArrowLeft.svelte';
import ArrowUpRightIcon from 'carbon-icons-svelte/lib/ArrowUpRight.svelte';
import Container from './Container.svelte';
import IconButton from '../../../IconButton/index.svelte';
import CloseButton from '../../../Buttons/Close/index.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
import CloseButton from '$lib/components/Buttons/Close/index.svelte';
import HeaderForm from './HeaderForm.svelte';
import RequirementForm from './RequirementForm.svelte';
import DescriptionForm from './DescriptionForm.svelte';
@@ -14,10 +14,10 @@
import GoalsForm from './GoalsForm.svelte';
import ReviewsForm from './ReviewsForm.svelte';
import InstructorForm from './InstructorForm.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import { VARIANTS } from '../../../PrimaryButton/constants';
import { updateCourse } from '../../../../utils/services/courses';
import generateSlug from '../../../../utils/functions/generateSlug';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { updateCourse } from '$lib/utils/services/courses';
import generateSlug from '$lib/utils/functions/generateSlug';
export let course;
export let courseId;
@@ -136,7 +136,7 @@
isDisabled={loading}
/>
<IconButton onClick={handlePreview} disabled={loading || !course.slug}>
<ArrowUpRight24 class="carbon-icon" title="Preview" />
<ArrowUpRightIcon size={24} class="carbon-icon" title="Preview" />
</IconButton>
</div>
</div>
@@ -149,14 +149,14 @@
on:click={handleSectionSelect(section.key)}
>
<p class="dark:text-white mr-2">{section.title} section</p>
<ChevronRight24 class="carbon-class" />
<ChevronRightIcon size={24} class="carbon-class" />
</button>
{/each}
{:else}
<!-- Title -->
<div class="flex items-center {borderBottomGrey} w-full">
<IconButton onClick={handleClose}>
<ArrowLeft24 class="carbon-icon" title="Go back" />
<ArrowLeftIcon size={24} class="carbon-icon" title="Go back" />
</IconButton>
<h3 class="dark:text-white">{selectedSection.title}</h3>
</div>
@@ -1,8 +1,8 @@
<script lang="ts">
import PrimaryButton from '../../PrimaryButton/index.svelte';
import { VARIANTS } from '../../PrimaryButton/constants';
import type { Course } from '../../../utils/types';
import getCurrencyFormatter from '../../../utils/functions/getCurrencyFormatter';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import type { Course } from '$lib/utils/types';
import getCurrencyFormatter from '$lib/utils/functions/getCurrencyFormatter';
import get from 'lodash/get';
export let className = '';
@@ -3,25 +3,25 @@
import get from 'lodash/get';
import { onMount } from 'svelte';
import pluralize from 'pluralize';
import { stores } from '@sapper/app';
import { page } from '$app/stores';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import Notebook from 'carbon-icons-svelte/lib/Notebook16/Notebook16.svelte'; //note
import PresentationFile from 'carbon-icons-svelte/lib/PresentationFile16/PresentationFile16.svelte'; // exercise
import Video from 'carbon-icons-svelte/lib/Video16/Video16.svelte'; //video
import PageNumber from 'carbon-icons-svelte/lib/PageNumber16/PageNumber16.svelte';
import PlayFilled from 'carbon-icons-svelte/lib/PlayFilled16/PlayFilled16.svelte';
import PrimaryButton from '../PrimaryButton/index.svelte';
import Notebook from 'carbon-icons-svelte/lib/Notebook.svelte'; //note
import PresentationFile from 'carbon-icons-svelte/lib/PresentationFile.svelte'; // exercise
import Video from 'carbon-icons-svelte/lib/Video.svelte'; //video
import PageNumber from 'carbon-icons-svelte/lib/PageNumber.svelte';
import PlayFilled from 'carbon-icons-svelte/lib/PlayFilled.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import PricingSection from './components/PricingSection.svelte';
import { getLectureNo } from '../Course/function';
import { NAV_ITEMS } from './constants';
import Avatar from '../../components/Avatar/index.svelte';
import Avatar from '$lib/components/Avatar/index.svelte';
import Chip from '../Chip/index.svelte';
import { getEmbedId } from '../../utils/functions/formatYoutubeVideo';
import type { Course, Lesson, Review } from '../../utils/types';
import { getEmbedId } from '$lib/utils/functions/formatYoutubeVideo';
import type { Course, Lesson, Review } from '$lib/utils/types';
import Modal from '../Modal/index.svelte';
import { reviewsModalStore } from './store';
import { VARIANTS } from './../PrimaryButton/constants';
import { VARIANTS } from './$lib/components/PrimaryButton/constants';
dayjs.extend(relativeTime);
@@ -47,7 +47,6 @@
// initialize the expandDescription array with 'false' values for each review.
let expandDescription = Array(reviews.length).fill(false);
const { page } = stores();
// const paystackApi = paystack('');
let activeNav = NAV_ITEMS[0].key;
@@ -183,7 +182,7 @@
<nav class="flex items-center border-b border-gray-300 pb-3">
{#each NAV_ITEMS as navItem}
<a
href="{$page.path}{navItem.key}"
href="{$page.url.pathname}{navItem.key}"
class="{navItem.key === activeNav &&
'active text-blue-700'} rounded-lg px-2 mr-6 text-slate-700 font-normal hover:bg-slate-100 hover:text-slate-900"
>
@@ -256,24 +255,24 @@
<div class="flex items-center">
{#if lesson.slide_url}
<span class="text-sm font-light flex w-2/4"
><PresentationFile class="mr-1" />1 slide</span
><PresentationFile size={16} class="mr-1" />1 slide</span
>
{/if}
{#if lesson.note}
<span class="text-sm font-light flex w-2/4"
><Notebook class="mr-1" />1 note</span
><Notebook size={16} class="mr-1" />1 note</span
>
{/if}
</div>
<div class="flex items-center">
{#if lesson.video_url}
<span class="text-sm font-light flex w-2/4"
><Video class="mr-1" />1 video</span
><Video size={16} class="mr-1" />1 video</span
>
{/if}
{#if get(lesson, 'totalExercises[0].count')}
<span class="text-sm font-light flex w-2/4"
><PageNumber class="mr-1" />{pluralize(
><PageNumber size={16} class="mr-1" />{pluralize(
'exercise',
get(lesson, 'totalExercises[0].count', 0),
true
@@ -436,7 +435,7 @@
{get(instructor, 'role', '')}
</p>
<p class="dark:text-white text-md font-light flex items-center">
<PlayFilled class="text-blue-700" />
<PlayFilled size={16} class="text-blue-700" />
<span class="ml-1"
>{get(instructor, 'courseNo', '')} courses</span
>
@@ -1,4 +1,4 @@
import { supabase } from '../../utils/functions/supabase';
import { supabase } from '$lib/utils/functions/supabase';
export async function fetchCourses(profileId) {
if (!profileId) return;
@@ -1,10 +1,10 @@
<script lang="ts">
import Dropdown from '../../../Dropdown/index.svelte';
import { copyCourseModal } from '../../store';
import { ROLE } from '../../../../utils/constants/roles';
import getCurrencyFormatter from '../../../../utils/functions/getCurrencyFormatter';
import OverflowMenuHorizontal20 from 'carbon-icons-svelte/lib/OverflowMenuHorizontal20';
import ArrowRight from 'carbon-icons-svelte/lib/ArrowRight24';
import Dropdown from '$lib/components/Dropdown/index.svelte';
import { copyCourseModal } from '$lib/components/Courses/store';
import { ROLE } from '$lib/utils/constants/roles';
import getCurrencyFormatter from '$lib/utils/functions/getCurrencyFormatter';
import OverflowMenuHorizontalIcon from 'carbon-icons-svelte/lib/OverflowMenuHorizontal.svelte';
import ArrowRight from 'carbon-icons-svelte/lib/ArrowRight.svelte';
export let bannerImage: string | undefined;
export let id = '';
@@ -60,7 +60,7 @@
isIcon={true}
>
<div class="p-1 rounded-full bg-white dark:bg-gray-600">
<OverflowMenuHorizontal20 class="carbon-icon" />
<OverflowMenuHorizontalIcon size={20} class="carbon-icon" />
</div>
</Dropdown>
{/if}
@@ -83,9 +83,13 @@
<p class="dark:text-white">{totalLessons} lessons</p>
{#if isOnLandingPage}
<ArrowRight class="carbon-class" />
<ArrowRight size={24} class="carbon-class" />
{:else}
<div class="rounded bg-{isPublished ? 'green' : 'red'}-200 py-1 px-2">
<div
class="rounded dark:text-white bg-{isPublished
? 'green'
: 'red'}-200 py-1 px-2"
>
{#if isPublished}
Published
{:else}
@@ -1,12 +1,15 @@
<script>
import { goto } from '@sapper/app';
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import Modal from '../../../Modal/index.svelte';
import { snackbarStore } from '../../../Snackbar/store';
import { SNACKBAR_SEVERITY } from '../../../Snackbar/constants';
import TextField from '../../../Form/TextField.svelte';
import { copyCourseModalInitialState, copyCourseModal } from '../../store';
import { cloneCourse } from '../../../../utils/services/courses/clone';
import { goto } from '$app/navigation';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import { snackbarStore } from '$lib/components/Snackbar/store';
import { SNACKBAR_SEVERITY } from '$lib/components/Snackbar/constants';
import TextField from '$lib/components/Form/TextField.svelte';
import {
copyCourseModalInitialState,
copyCourseModal,
} from '$lib/components/Courses/store';
import { cloneCourse } from '$lib/utils/services/courses/clone';
// clone, show spinner and redirect to new course
async function createCourse() {
@@ -1,15 +1,15 @@
<script>
import PrimaryButton from '../../../PrimaryButton/index.svelte';
import Modal from '../../../Modal/index.svelte';
import TextField from '../../../Form/TextField.svelte';
import TextArea from '../../../Form/TextArea.svelte';
import { courses, createCourseModal } from '../../../Courses/store';
import { validateForm } from '../../../Courses/functions';
import { ROLE } from '../../../../utils/constants/roles';
import { addGroupMember } from '../../../../utils/services/courses';
import { supabase } from '../../../../utils/functions/supabase';
import { profile } from '../../../../utils/store/user';
import { currentOrg } from '../../../../utils/store/org';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import Modal from '$lib/components/Modal/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte';
import { courses, createCourseModal } from '$lib/components/Courses/store';
import { validateForm } from '$lib/components/Courses/functions';
import { ROLE } from '$lib/utils/constants/roles';
import { addGroupMember } from '$lib/utils/services/courses';
import { supabase } from '$lib/utils/functions/supabase';
import { profile } from '$lib/utils/store/user';
import { currentOrg } from '$lib/utils/store/org';
let errors = {
emails: '',
@@ -26,17 +26,21 @@
// 1. Create group
const { data: newGroup } = await supabase
.from('group')
.insert({ name: title, description, organization_id: $currentOrg.id });
.insert({ name: title, description, organization_id: $currentOrg.id })
.select();
console.log(`newGroup`, newGroup);
const { id: group_id } = newGroup[0];
// 2. Create course with group_id
const { data: newCourse } = await supabase.from('course').insert({
title,
description,
group_id,
});
const { data: newCourse } = await supabase
.from('course')
.insert({
title,
description,
group_id,
})
.select();
console.log(`newCourse`, newCourse);
courses.update((_courses) => [..._courses, newCourse[0]]);
@@ -1,4 +1,4 @@
import { validateEmail } from '../../utils/functions/validateEmail';
import { validateEmail } from '$lib/utils/functions/validateEmail';
export function validateForm(fields) {
let hasError = false;

Some files were not shown because too many files have changed in this diff Show More