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
+1 -1
View File
@@ -2,6 +2,6 @@
/node_modules/ /node_modules/
/src/node_modules/@sapper/ /src/node_modules/@sapper/
yarn-error.log yarn-error.log
/__sapper__/ .svelte-kit/
.env .env
/dist/ /dist/
-1
View File
@@ -1 +0,0 @@
{"imports":{"netlify:edge":"https://edge.netlify.com/v1/index.ts"},"scopes":{}}
@@ -1 +0,0 @@
module.exports = require('./src/netlify/functions/create-org-site.js')
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
npm_config_registry=https://registry.npmjs.org
+1 -1
View File
@@ -1 +1 @@
v14.17.5 v18.16.0
+8
View File
@@ -17,3 +17,11 @@ I personally believe that in the future (as already exists in most countries), t
3. All in one place 3. All in one place
4. Empower hybrid form of learning 4. Empower hybrid form of learning
5. We Automate routine tasks and you focus on the health of your classroom. 5. We Automate routine tasks and you focus on the health of your classroom.
## Installation of modules
```
npm i --legacy-peer-deps --registry=https://registry.npmjs.org
```
Note: Make sure you are using Node 18
+3 -4
View File
@@ -1,6 +1,5 @@
[[redirects]]
from = "/*"
to = "/404.html"
status = 404
[build.environment] [build.environment]
NODE_OPTIONS = "--max_old_space_size=4096" NODE_OPTIONS = "--max_old_space_size=4096"
[build]
command = "npm run build"
publish = "build"
+3259 -6673
View File
File diff suppressed because it is too large Load Diff
+50 -78
View File
@@ -4,95 +4,67 @@
"version": "0.0.1", "version": "0.0.1",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
"dev": "sapper dev", "dev": "vite dev",
"build": "sapper build --legacy", "build": "vite build --legacy",
"export": "sapper export --legacy --entry \"/ /404 login signup forgot onboarding courses org lms course\"", "export": "vite build --entry \"/ /404 login signup forgot onboarding courses org lms course\"",
"postexport": "mv __sapper__/export/404/index.html __sapper__/export/404.html", "postexport": "mv __sapper__/export/404/index.html __sapper__/export/404.html",
"start": "node __sapper__/build", "start": "node build",
"electron": "wait-on http://localhost:3000 && electron .", "prepare": "svelte-kit sync"
"electron-dev": "concurrently \"npm run dev\" \"npm run electron\"",
"preelectron-pack": "npm run export",
"electron-pack": "electron-builder"
}, },
"dependencies": { "dependencies": {
"@rollup/plugin-json": "^4.1.0", "@sentry/browser": "^7.61.0",
"@sentry/browser": "^6.13.3", "@sentry/integrations": "^7.61.0",
"@sentry/integrations": "^6.13.3", "@sentry/tracing": "^7.61.0",
"@sentry/tracing": "^6.13.3", "@supabase/supabase-js": "^2.31.0",
"@supabase/supabase-js": "^1.20.0", "@sveltejs/adapter-auto": "^2.1.0",
"@tailwindcss/forms": "^0.3.2", "@tailwindcss/forms": "^0.5.4",
"@types/marked": "^5.0.1",
"@types/paystack": "^2.0.1", "@types/paystack": "^2.0.1",
"@types/pluralize": "0.0.29", "@types/pluralize": "0.0.30",
"body-parser": "^1.19.0", "autoprefixer": "^10.4.14",
"canvas-confetti": "^1.4.0", "body-parser": "^1.20.2",
"compression": "^1.7.1", "canvas-confetti": "^1.6.0",
"concurrently": "^8.1.0", "cookie-parser": "^1.4.6",
"cookie-parser": "^1.4.5", "copy-to-clipboard": "^3.3.3",
"copy-to-clipboard": "^3.3.1", "hotkeys-js": "^3.11.2",
"electron-serve": "^1.1.0",
"express": "^4.17.1",
"hotkeys-js": "^3.8.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"marked": "^1.2.7", "marked": "^6.0.0",
"netlify": "^13.1.0", "netlify": "^13.1.10",
"node-sass": "^6.0.0",
"paystack": "^2.0.1",
"pluralize": "^8.0.0", "pluralize": "^8.0.0",
"polka": "next",
"quill": "^1.3.7", "quill": "^1.3.7",
"sapper-environment": "^1.0.1", "sirv": "^2.0.3",
"sirv": "^1.0.0",
"svelte-easy-crop": "^1.0.4",
"wait-on": "^7.0.1", "wait-on": "^7.0.1",
"zod": "^3.19.1" "zod": "^3.21.4"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.0.0", "@babel/core": "^7.22.9",
"@babel/plugin-syntax-dynamic-import": "^7.0.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.0.0", "@babel/plugin-transform-runtime": "^7.22.9",
"@babel/preset-env": "^7.0.0", "@babel/preset-env": "^7.22.9",
"@babel/runtime": "^7.0.0", "@babel/runtime": "^7.22.6",
"@fortawesome/free-brands-svg-icons": "^5.15.3", "@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^5.15.3", "@fortawesome/free-regular-svg-icons": "^6.4.0",
"@rollup/plugin-babel": "^5.0.0", "@sveltejs/kit": "^1.22.4",
"@rollup/plugin-commonjs": "^14.0.0", "@tailwindcss/typography": "^0.5.9",
"@rollup/plugin-node-resolve": "^8.0.0", "@types/lodash": "^4.14.196",
"@rollup/plugin-replace": "^2.4.2", "carbon-components-svelte": "^0.79.0",
"@rollup/plugin-typescript": "^8.3.0", "carbon-icons-svelte": "^12.1.0",
"@tailwindcss/typography": "^0.3.1", "dotenv": "^16.3.1",
"@types/lodash": "^4.14.191", "postcss": "^8.4.24",
"carbon-components-svelte": "^0.70.13", "postcss-load-config": "^4.0.1",
"carbon-icons-svelte": "^10.21.0", "sass": "^1.64.2",
"dotenv": "^10.0.0", "svelte": "^4.1.2",
"electron": "^25.0.1", "svelte-awesome": "^3.2.1",
"electron-builder": "^23.6.0",
"postcss": "^8.0.9",
"postcss-load-config": "^2.1.0",
"rollup": "^2.3.4",
"rollup-plugin-svelte": "^6.0.0",
"rollup-plugin-terser": "^7.0.0",
"sapper": "^0.28.0",
"sass": "^1.32.13",
"svelte": "^3.17.3",
"svelte-awesome": "^2.3.1",
"svelte-calendar": "^3.1.6", "svelte-calendar": "^3.1.6",
"svelte-dnd-action": "^0.9.9", "svelte-dnd-action": "^0.9.24",
"svelte-loading-spinners": "^0.1.7", "svelte-loading-spinners": "^0.3.4",
"svelte-preprocess": "^4.7.3", "svelte-preprocess": "^5.0.4",
"tailwindcss": "^2.1.2", "tailwindcss": "^3.3.2",
"tslib": "^2.3.1", "tslib": "^2.6.1",
"typescript": "^4.1.3" "typescript": "^5.1.6",
"vite": "^4.4.8",
"autoprefixer": "^10.4.14"
}, },
"build": { "type": "module"
"icon": "static/logo-512.png",
"productName": "ClassroomIO",
"files": [
"__sapper__/export/**/*",
"main.js"
],
"win": {},
"linux": {},
"mac": {}
}
} }
+13
View File
@@ -0,0 +1,13 @@
const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");
const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer,
],
};
module.exports = config;
+5 -2
View File
@@ -1,3 +1,6 @@
module.exports = { export default {
plugins: [require('tailwindcss')], plugins: {
tailwindcss: {},
autoprefixer: {},
},
}; };
-150
View File
@@ -1,150 +0,0 @@
import resolve from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import commonjs from '@rollup/plugin-commonjs';
import svelte from 'rollup-plugin-svelte';
import babel from '@rollup/plugin-babel';
import { terser } from 'rollup-plugin-terser';
import config from 'sapper/config/rollup.js';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';
import json from '@rollup/plugin-json';
import sapperEnv from 'sapper-environment';
import pkg from './package.json';
const mode = process.env.NODE_ENV;
const dev = mode === 'development';
// const sourcemap = dev ? false : 'inline';
const sourcemap = 'inline';
const legacy = !!process.env.SAPPER_LEGACY_BUILD;
const onwarn = (warning, onwarn) => {
if (warning.code === 'THIS_IS_UNDEFINED') return;
return (
(warning.code === 'MISSING_EXPORT' && /'preload'/.test(warning.message)) ||
(warning.code === 'CIRCULAR_DEPENDENCY' &&
/[/\\]@sapper[/\\]/.test(warning.message)) ||
onwarn(warning)
);
};
const preprocess = sveltePreprocess({ postcss: true, sourceMap: !!sourcemap });
export default {
client: {
input: config.client.input(),
output: config.client.output(),
plugins: [
replace({
...sapperEnv(),
'process.browser': true,
'process.env.NODE_ENV': JSON.stringify(mode),
preventAssignment: true,
}),
typescript({
noEmitOnError: !dev,
sourceMap: !!sourcemap,
}),
json(),
svelte({
preprocess,
dev,
hydratable: true,
emitCss: true,
}),
resolve({
preferBuiltins: false,
browser: true,
dedupe: ['svelte'],
}),
commonjs({
sourceMap: !!sourcemap,
}),
legacy &&
babel({
extensions: ['.js', '.mjs', '.html', '.svelte'],
babelHelpers: 'runtime',
exclude: ['node_modules/@babel/**'],
presets: [
[
'@babel/preset-env',
{
targets: '> 0.25%, not dead',
},
],
],
plugins: [
'@babel/plugin-syntax-dynamic-import',
[
'@babel/plugin-transform-runtime',
{
useESModules: true,
},
],
],
}),
!dev &&
terser({
module: true,
}),
],
preserveEntrySignatures: false,
onwarn,
},
server: {
input: config.server.input(),
output: { ...config.server.output(), sourcemap },
plugins: [
replace({
'process.browser': false,
'process.env.NODE_ENV': JSON.stringify(mode),
preventAssignment: true,
}),
typescript({
noEmitOnError: !dev,
sourceMap: !!sourcemap,
}),
svelte({
preprocess,
generate: 'ssr',
hydratable: true,
dev,
}),
resolve({
preferBuiltins: false,
dedupe: ['svelte'],
}),
commonjs({
sourceMap: !!sourcemap,
}),
],
external: Object.keys(pkg.dependencies).concat(
require('module').builtinModules
),
preserveEntrySignatures: 'strict',
onwarn,
},
// serviceworker: {
// input: config.serviceworker.input(),
// output: config.serviceworker.output(),
// plugins: [
// resolve(),
// replace({
// "process.browser": true,
// "process.env.NODE_ENV": JSON.stringify(mode)
// }),
// commonjs(),
// !dev && terser()
// ],
// preserveEntrySignatures: false,
// onwarn
// }
};
-290
View File
@@ -1,290 +0,0 @@
/**
* Run this script to convert the project to TypeScript. This is only guaranteed to work
* on the unmodified default template; if you have done code changes you are likely need
* to touch up the generated project manually.
*/
// @ts-check
const fs = require("fs");
const path = require("path");
const { argv } = require("process");
const projectRoot = argv[2] || path.join(__dirname, "..");
function warn(message) {
console.warn("Warning: " + message);
}
function replaceInFile(fileName, replacements) {
if (fs.existsSync(fileName)) {
let contents = fs.readFileSync(fileName, "utf8");
let hadUpdates = false;
replacements.forEach(([from, to]) => {
const newContents = contents.replace(from, to);
const isAlreadyApplied = typeof to !== "string" || contents.includes(to);
if (newContents !== contents) {
contents = newContents;
hadUpdates = true;
} else if (!isAlreadyApplied) {
warn(`Wanted to update "${from}" in ${fileName}, but did not find it.`);
}
});
if (hadUpdates) {
fs.writeFileSync(fileName, contents);
} else {
console.log(`${fileName} had already been updated.`);
}
} else {
warn(`Wanted to update ${fileName} but the file did not exist.`);
}
}
function createFile(fileName, contents) {
if (fs.existsSync(fileName)) {
warn(
`Wanted to create ${fileName}, but it already existed. Leaving existing file.`
);
} else {
fs.writeFileSync(fileName, contents);
}
}
function addDepsToPackageJson() {
const pkgJSONPath = path.join(projectRoot, "package.json");
const packageJSON = JSON.parse(fs.readFileSync(pkgJSONPath, "utf8"));
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
"@rollup/plugin-typescript": "^6.0.0",
"@tsconfig/svelte": "^1.0.10",
"@types/compression": "^1.7.0",
"@types/node": "^14.11.1",
"@types/polka": "^0.5.1",
"svelte-check": "^1.0.46",
"svelte-preprocess": "^4.3.0",
tslib: "^2.0.1",
typescript: "^4.0.3"
});
// Add script for checking
packageJSON.scripts = Object.assign(packageJSON.scripts, {
validate: "svelte-check --ignore src/node_modules/@sapper"
});
// Write the package JSON
fs.writeFileSync(pkgJSONPath, JSON.stringify(packageJSON, null, " "));
}
function changeJsExtensionToTs(dir) {
const elements = fs.readdirSync(dir, { withFileTypes: true });
for (let i = 0; i < elements.length; i++) {
if (elements[i].isDirectory()) {
changeJsExtensionToTs(path.join(dir, elements[i].name));
} else if (elements[i].name.match(/^((?!json).)*js$/)) {
fs.renameSync(
path.join(dir, elements[i].name),
path.join(dir, elements[i].name).replace(".js", ".ts")
);
}
}
}
function updateSingleSvelteFile({ view, vars, contextModule }) {
replaceInFile(path.join(projectRoot, "src", `${view}.svelte`), [
[
/(?:<script)(( .*?)*?)>/gm,
(m, attrs) =>
`<script${attrs}${!attrs.includes('lang="ts"') ? ' lang="ts"' : ""}>`
],
...(vars
? vars.map(({ name, type }) => [
`export let ${name};`,
`export let ${name}: ${type};`
])
: []),
...(contextModule ? contextModule.map(({ js, ts }) => [js, ts]) : [])
]);
}
// Switch the *.svelte file to use TS
function updateSvelteFiles() {
[
{
view: "components/Nav",
vars: [{ name: "segment", type: "string" }]
},
{
view: "routes/_layout",
vars: [{ name: "segment", type: "string" }]
},
{
view: "routes/_error",
vars: [
{ name: "status", type: "number" },
{ name: "error", type: "Error" }
]
},
{
view: "routes/blog/index",
vars: [
{ name: "posts", type: "{ id: string; title: string, html: any }[]" }
],
contextModule: [
{
js: ".then(r => r.json())",
ts: ".then((r: { json: () => any; }) => r.json())"
},
{
js: ".then(posts => {",
ts: ".then((posts: { id: string; title: string, html: any }[]) => {"
}
]
},
{
view: "routes/blog/[id]",
vars: [
{ name: "post", type: "{ id: string; title: string, html: any }" }
]
}
].forEach(updateSingleSvelteFile);
}
function updateRollupConfig() {
// Edit rollup config
replaceInFile(path.join(projectRoot, "rollup.config.js"), [
// Edit imports
[
/'rollup-plugin-terser';\n(?!import sveltePreprocess)/,
`'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';`
],
// Edit inputs
[
/(?<!THIS_IS_UNDEFINED[^\n]*\n\s*)onwarn\(warning\);/,
`(warning.code === 'THIS_IS_UNDEFINED') ||\n\tonwarn(warning);`
],
[
/input: config.client.input\(\)(?!\.replace)/,
`input: config.client.input().replace(/\.js$/, '.ts')`
],
[
/input: config.server.input\(\)(?!\.replace)/,
`input: { server: config.server.input().server.replace(/\.js$/, ".ts") }`
],
[
/input: config.serviceworker.input\(\)(?!\.replace)/,
`input: config.serviceworker.input().replace(/\.js$/, '.ts')`
],
// Add preprocess to the svelte config, this is tricky because there's no easy signifier.
// Instead we look for 'hydratable: true,'
[
/hydratable: true(?!,\n\s*preprocess)/g,
"hydratable: true,\n\t\t\t\tpreprocess: sveltePreprocess()"
],
// Add TypeScript
[
/commonjs\(\)(?!,\n\s*typescript)/g,
"commonjs(),\n\t\t\ttypescript({ sourceMap: dev })"
]
]);
}
function updateServiceWorker() {
replaceInFile(path.join(projectRoot, "src", "service-worker.ts"), [
[`shell.concat(files);`, `(shell as string[]).concat(files as string[]);`],
[
`'install', event =>`,
`'install', <EventType extends ExtendableEvent>(event: EventType) =>`
],
[
`self.skipWaiting();`,
`((self as any) as ServiceWorkerGlobalScope).skipWaiting();`
],
[
`'activate', event =>`,
`'activate', <EventType extends ExtendableEvent>(event: EventType) =>`
],
[
`self.clients.claim();`,
`((self as any) as ServiceWorkerGlobalScope).clients.claim();`
],
[
`'fetch', event =>`,
`'fetch', <EventType extends FetchEvent>(event: EventType) =>`
]
]);
}
function createTsConfig() {
const tsconfig = `{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"lib": ["DOM", "ES2017", "WebWorker"]
},
"include": ["src/**/*", "src/node_modules/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "static/*"]
}`;
createFile(path.join(projectRoot, "tsconfig.json"), tsconfig);
}
// Adds the extension recommendation
function configureVsCode() {
const dir = path.join(projectRoot, ".vscode");
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
createFile(
path.join(projectRoot, ".vscode", "extensions.json"),
`{"recommendations": ["svelte.svelte-vscode"]}`
);
}
function deleteThisScript() {
fs.unlinkSync(path.join(__filename));
// Check for Mac's DS_store file, and if it's the only one left remove it
const remainingFiles = fs.readdirSync(path.join(__dirname));
if (remainingFiles.length === 1 && remainingFiles[0] === ".DS_store") {
fs.unlinkSync(path.join(__dirname, ".DS_store"));
}
// Check if the scripts folder is empty
if (fs.readdirSync(path.join(__dirname)).length === 0) {
// Remove the scripts folder
fs.rmdirSync(path.join(__dirname));
}
}
console.log("Adding TypeScript with Rollup...");
addDepsToPackageJson();
changeJsExtensionToTs(path.join(projectRoot, "src"));
updateSvelteFiles();
updateRollupConfig();
updateServiceWorker();
createTsConfig();
configureVsCode();
// Delete this script, but not during testing
if (!argv[2]) {
deleteThisScript();
}
console.log("Converted to TypeScript.");
if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
console.log(`\nYou will need to re-run 'npm install' to get started.`);
}
-11
View File
@@ -1,11 +0,0 @@
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "rotimi-best",
"license": "ISC"
}
-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 { export default {
isProd: process.env.NODE_ENV !== 'development',
supabaseConfig: { supabaseConfig: {
bucketPath: bucketPath:
'https://koxqonvbkeakwvmdegcf.supabase.in/storage/v1/object/sign/', '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> <script>
import marked from 'marked'; import { marked } from 'marked';
import PageNav from '../../../PageNav/index.svelte'; import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from '../../../Buttons/Close/index.svelte'; import CloseButton from '$lib/components/Buttons/Close/index.svelte';
import TextField from '../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
// import SendButton from "../../../Buttons/Send/index.svelte"; // import SendButton from "$lib/components/Buttons/Send/index.svelte";
export let handleClose; export let handleClose;
@@ -1,6 +1,6 @@
<script> <script>
import PageNav from "../../../PageNav/index.svelte"; import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from "../../../Buttons/Close/index.svelte"; import CloseButton from '$lib/components/Buttons/Close/index.svelte';
export let handleClose; export let handleClose;
</script> </script>
@@ -1,20 +1,20 @@
<script> <script>
import FormSection from "./FormSection.svelte"; import FormSection from './FormSection.svelte';
import PrimaryButton from "../../../../PrimaryButton/index.svelte"; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from "../../../../PrimaryButton/constants"; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
export let title = "Poll"; export let title = 'Poll';
export let onSubmit; export let onSubmit;
export let onCancel; export let onCancel;
let values = { let values = {
question: "", question: '',
author: "", author: '',
isPublic: false, isPublic: false,
expiration: "", expiration: '',
options: [ options: [
{ {
label: "", label: '',
selectedBy: [], selectedBy: [],
}, },
], ],
@@ -26,7 +26,7 @@
options: [ options: [
...values.options, ...values.options,
{ {
label: "", label: '',
selectedBy: [], selectedBy: [],
}, },
], ],
@@ -58,7 +58,7 @@
{#each values.options as option, index} {#each values.options as option, index}
<FormSection <FormSection
label={index === 0 && "Options"} label={index === 0 && 'Options'}
bind:value={option.label} bind:value={option.label}
handleLabelButton={handleAddOptions} handleLabelButton={handleAddOptions}
handleInputButton={handleRemoveOptions(index)} handleInputButton={handleRemoveOptions(index)}
@@ -1,8 +1,8 @@
<script> <script>
import PageNav from '../../../PageNav/index.svelte'; import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from '../../../Buttons/Close/index.svelte'; import CloseButton from '$lib/components/Buttons/Close/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '../../../PrimaryButton/constants'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import CreatePollForm from './components/CreatePollForm.svelte'; import CreatePollForm from './components/CreatePollForm.svelte';
import Poll from './components/Poll.svelte'; import Poll from './components/Poll.svelte';
import Tabs from './components/Tabs.svelte'; import Tabs from './components/Tabs.svelte';
@@ -1,10 +1,10 @@
<script> <script>
import marked from 'marked'; import { marked } from 'marked';
import CheckmarkOutline20 from 'carbon-icons-svelte/lib/CheckmarkOutline20'; import CheckmarkOutline from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
import PageNav from '../../../PageNav/index.svelte'; import PageNav from '$lib/components/PageNav/index.svelte';
import CloseButton from '../../../Buttons/Close/index.svelte'; import CloseButton from '$lib/components/Buttons/Close/index.svelte';
import Vote from '../../../Vote/index.svelte'; import Vote from '$lib/components/Vote/index.svelte';
import TextField from '../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
export let handleClose; export let handleClose;
let bodyRef; let bodyRef;
@@ -108,7 +108,7 @@
class={`${question.answered && 'active'}`} class={`${question.answered && 'active'}`}
on:click={handleMarkAnswered(question.id)} on:click={handleMarkAnswered(question.id)}
> >
<CheckmarkOutline20 class="carbon-icon" /> <CheckmarkOutline size={20} class="carbon-icon" />
</button> </button>
</div> </div>
{/each} {/each}
@@ -1,11 +1,11 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import hotkeys from 'hotkeys-js'; import hotkeys from 'hotkeys-js';
import Forum24 from 'carbon-icons-svelte/lib/Forum24'; import Forum from 'carbon-icons-svelte/lib/Forum.svelte';
import AlignBoxTopLeft24 from 'carbon-icons-svelte/lib/AlignBoxTopLeft24'; import AlignBoxTopLeft from 'carbon-icons-svelte/lib/AlignBoxTopLeft.svelte';
import SendAlt24 from 'carbon-icons-svelte/lib/SendAlt24'; import SendAlt from 'carbon-icons-svelte/lib/SendAlt.svelte';
import ChartPie24 from 'carbon-icons-svelte/lib/ChartPie24'; import ChartPie from 'carbon-icons-svelte/lib/ChartPie.svelte';
import IconButton from '../IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
import QandA from './components/QandA/index.svelte'; import QandA from './components/QandA/index.svelte';
import LiveChat from './components/LiveChat/index.svelte'; import LiveChat from './components/LiveChat/index.svelte';
@@ -56,7 +56,7 @@
onClick={handleAppClick} onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.LIVE_CHAT === selectedApp} selected={APPS_CONSTANTS.APPS.LIVE_CHAT === selectedApp}
> >
<SendAlt24 class="carbon-icon" /> <SendAlt size={24} class="carbon-icon" />
</IconButton> </IconButton>
<IconButton <IconButton
@@ -65,7 +65,7 @@
onClick={handleAppClick} onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.QANDA === selectedApp} selected={APPS_CONSTANTS.APPS.QANDA === selectedApp}
> >
<Forum24 class="carbon-icon" /> <Forum size={24} class="carbon-icon" />
</IconButton> </IconButton>
<IconButton <IconButton
@@ -74,7 +74,7 @@
onClick={handleAppClick} onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.NOTES === selectedApp} selected={APPS_CONSTANTS.APPS.NOTES === selectedApp}
> >
<AlignBoxTopLeft24 class="carbon-icon" /> <AlignBoxTopLeft size={24} class="carbon-icon" />
</IconButton> </IconButton>
<IconButton <IconButton
@@ -83,7 +83,7 @@
onClick={handleAppClick} onClick={handleAppClick}
selected={APPS_CONSTANTS.APPS.POLL === selectedApp} selected={APPS_CONSTANTS.APPS.POLL === selectedApp}
> >
<ChartPie24 class="carbon-icon" /> <ChartPie size={24} class="carbon-icon" />
</IconButton> </IconButton>
</div> </div>
@@ -1,6 +1,6 @@
<script> <script>
import PrimaryButton from '../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '../PrimaryButton/constants'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import GoogleIconColored from '../Icons/GoogleIconColored.svelte'; import GoogleIconColored from '../Icons/GoogleIconColored.svelte';
export let supabase; export let supabase;
@@ -13,7 +13,7 @@
async function signInWithGoogle() { async function signInWithGoogle() {
try { try {
console.log('signInWithGoogle'); console.log('signInWithGoogle');
const { user, session, error } = await supabase.auth.signIn({ const { user, session, error } = await supabase.auth.signInWithOAuth({
provider: 'google', 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> <script>
export let value; export let value = 0;
export let className; export let className = '';
</script> </script>
<p class={className ? className : 'bg-set mt-2'}>{value}</p> <p class={className ? className : 'bg-set mt-2'}>{value}</p>
@@ -1,5 +1,5 @@
<script> <script>
import marked from 'marked'; import { marked } from 'marked';
export let code = ''; export let code = '';
</script> </script>
@@ -1,5 +1,5 @@
<script> <script>
import PageNav from "../../../../PageNav/index.svelte"; import PageNav from '$lib/components/PageNav/index.svelte';
</script> </script>
<PageNav title="Attendance" /> <PageNav title="Attendance" />
@@ -4,14 +4,14 @@
RadioButton, RadioButton,
Toggle, Toggle,
} from 'carbon-components-svelte'; } from 'carbon-components-svelte';
import { goto } from '@sapper/app'; import { goto } from '$app/navigation';
import { updateCourse } from '../../../../utils/services/courses'; import { updateCourse } from '$lib/utils/services/courses';
import PrimaryButton from '../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import TextArea from '../../../Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import Professional from './certificates/Professional.svelte'; import Professional from './certificates/Professional.svelte';
import Plain from './certificates/Plain.svelte'; import Plain from './certificates/Plain.svelte';
import { course } from '../../store'; import { course } from '$lib/components/Course/store';
import { currentOrg } from '../../../../utils/store/org'; import { currentOrg } from '$lib/utils/store/org';
const studentNamePlaceholder = 'Name of student'; const studentNamePlaceholder = 'Name of student';
const themes = ['professional', 'plain']; const themes = ['professional', 'plain'];
@@ -59,7 +59,7 @@
{#each themes as theme} {#each themes as theme}
<div class="flex mr-3"> <div class="flex mr-3">
<RadioButton value={theme} size="sm" /> <RadioButton value={theme} size="sm" />
<img src={`./${theme}.svg`} alt="themes" /> <img src={`/${theme}.svg`} alt="themes" />
</div> </div>
{/each} {/each}
</RadioButtonGroup> </RadioButtonGroup>
@@ -1,9 +1,9 @@
<script> <script>
import { Toggle } from 'carbon-components-svelte'; import { Toggle } from 'carbon-components-svelte';
import Modal from '../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import TextArea from '../../../Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import TextField from '../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import { issueCertificateModal, resetForm } from './store'; import { issueCertificateModal, resetForm } from './store';
const onToggle = (e) => { const onToggle = (e) => {
@@ -1,5 +1,5 @@
<script> <script>
import { course } from '../../../store'; import { course } from '$lib/components/Course/store';
import UnlockedCertificate from './UnlockedCertificate.svelte'; import UnlockedCertificate from './UnlockedCertificate.svelte';
import LockedCertificate from './LockedCertificate.svelte'; import LockedCertificate from './LockedCertificate.svelte';
</script> </script>
@@ -1,5 +1,5 @@
<script> <script>
import { course } from '../../../store'; import { course } from '$lib/components/Course/store';
</script> </script>
<section class="studentContainer flex items-center justify-center w-full"> <section class="studentContainer flex items-center justify-center w-full">
@@ -1,8 +1,8 @@
<script> <script>
import { course } from '../../../store'; import { course } from '$lib/components/Course/store';
import { currentOrg } from '../../../../../utils/store/org'; import { currentOrg } from '$lib/utils/store/org';
import { profile } from '../../../../../utils/store/user'; import { profile } from '$lib/utils/store/user';
import PrimaryButton from '../../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
let isLoading = false; let isLoading = false;
@@ -1,8 +1,8 @@
<script> <script>
import { course } from '../../../store'; import { course } from '$lib/components/Course/store';
import { currentOrg } from '../../../../../utils/store/org'; import { currentOrg } from '$lib/utils/store/org';
export let studentName; export let studentName = '';
let borderwidth = 'border-4'; let borderwidth = 'border-4';
let bordercolor = 'border-pink-700'; let bordercolor = 'border-pink-700';
let logo = './logo-512.png'; let logo = './logo-512.png';
@@ -1,6 +1,6 @@
<script> <script>
import { course } from '../../../store'; import { course } from '$lib/components/Course/store';
import { currentOrg } from '../../../../../utils/store/org'; import { currentOrg } from '$lib/utils/store/org';
export let studentName; export let studentName;
let borderwidth = 'border-l-8'; let borderwidth = 'border-l-8';
@@ -1,8 +1,8 @@
<script> <script>
import Modal from '../../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/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'; import { deleteConfirmation } from '../store/exercise';
export let onDelete = () => {}; export let onDelete = () => {};
@@ -10,36 +10,34 @@
handleAnswerSelect, handleAnswerSelect,
addDynamicValue, addDynamicValue,
} from '../store/exercise'; } from '../store/exercise';
import Delete24 from 'carbon-icons-svelte/lib/Delete24'; import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte';
import AddFilled24 from 'carbon-icons-svelte/lib/AddFilled24'; import AddFilledIcon from 'carbon-icons-svelte/lib/AddFilled.svelte';
import CheckmarkFilled24 from 'carbon-icons-svelte/lib/CheckmarkFilled24'; import CheckmarkFilledIcon from 'carbon-icons-svelte/lib/CheckmarkFilled.svelte';
import CheckmarkOutline24 from 'carbon-icons-svelte/lib/CheckmarkOutline24'; import CheckmarkOutlineIcon from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
// import Subtract24 from "carbon-icons-svelte/lib/Subtract24";
import TextField from '../../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import Modal from '../../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import TextArea from '../../../../Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import Checkbox from '../../../../Form/Checkbox.svelte'; import Checkbox from '$lib/components/Form/Checkbox.svelte';
import DateTime from '../../../../Form/DateTime.svelte'; import DateTime from '$lib/components/Form/DateTime.svelte';
import RadioItem from '../../../../Form/RadioItem.svelte'; import RadioItem from '$lib/components/Form/RadioItem.svelte';
import IconButton from '../../../../IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
import ErrorMessage from '../../../../ErrorMessage/index.svelte'; import ErrorMessage from '$lib/components/ErrorMessage/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import EditContent from '../../../../EditContent/index.svelte'; import EditContent from '$lib/components/EditContent/index.svelte';
import { VARIANTS } from '../../../../PrimaryButton/constants'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import Select from '../../../../Form/Select.svelte'; import Select from '$lib/components/Form/Select.svelte';
import QuestionContainer from '../../../../QuestionContainer/index.svelte'; import QuestionContainer from '$lib/components/QuestionContainer/index.svelte';
import DeleteConfirmationModal from './DeleteConfirmation.svelte'; import DeleteConfirmationModal from './DeleteConfirmation.svelte';
import OrderModal from './OrderModal.svelte'; import OrderModal from './OrderModal.svelte';
import { import {
QUESTION_TYPE, QUESTION_TYPE,
QUESTION_TYPES, QUESTION_TYPES,
} from '../../../../Question/constants'; } from '$lib/components/Question/constants';
import { filterOutDeleted } from './functions'; import { filterOutDeleted } from './functions';
import { deleteExercise } from '../../../../../utils/services/courses'; import { deleteExercise } from '$lib/utils/services/courses';
import { lesson } from '../store/lessons'; import { lesson } from '../store/lessons';
// import EditContent from "../../../../EditContent/index.svelte"; // import EditContent from "$lib/components/EditContent/index.svelte";
// import readme from "../../readme.js";
// let value = readme; // let value = readme;
const extraActions = ['Code Snippets', 'Upload image']; const extraActions = ['Code Snippets', 'Upload image'];
@@ -221,7 +219,7 @@
options={extraActions} options={extraActions}
handleOptionClick={handleOptionClick(question.id)} handleOptionClick={handleOptionClick(question.id)}
> >
<AddFilled24 class="carbon-icon" /> <AddFilledIcon class="carbon-icon" />
<p class="dark:text-white ml-2 text-gray-600">Add</p> <p class="dark:text-white ml-2 text-gray-600">Add</p>
</Dropdown> --> </Dropdown> -->
@@ -245,7 +243,7 @@
value="write-code" value="write-code"
onClick={() => handleCode(question.id, false)} onClick={() => handleCode(question.id, false)}
> >
<Delete24 class="carbon-icon" /> <TrashCanIcon size={24} class="carbon-icon" />
</IconButton> </IconButton>
</div> </div>
{/if} {/if}
@@ -264,7 +262,7 @@
value={option.id} value={option.id}
onClick={handleRemoveOption(question.id, option.id)} onClick={handleRemoveOption(question.id, option.id)}
> >
<Delete24 class="carbon-icon" /> <TrashCanIcon size={24} class="carbon-icon" />
</IconButton> </IconButton>
<IconButton <IconButton
value={option.id} value={option.id}
@@ -272,9 +270,9 @@
buttonClassName={option.is_correct && 'success'} buttonClassName={option.is_correct && 'success'}
> >
{#if option.is_correct} {#if option.is_correct}
<CheckmarkFilled24 class="carbon-icon" /> <CheckmarkFilledIcon size={24} class="carbon-icon" />
{:else} {:else}
<CheckmarkOutline24 class="carbon-icon" /> <CheckmarkOutlineIcon size={24} class="carbon-icon" />
{/if} {/if}
</IconButton> </IconButton>
</div> </div>
@@ -295,7 +293,7 @@
value={option.id} value={option.id}
onClick={handleRemoveOption(question.id, option.id)} onClick={handleRemoveOption(question.id, option.id)}
> >
<Delete24 class="carbon-icon" /> <TrashCanIcon size={24} class="carbon-icon" />
</IconButton> </IconButton>
<IconButton <IconButton
value={option.id} value={option.id}
@@ -303,9 +301,9 @@
buttonClassName={option.is_correct && 'success'} buttonClassName={option.is_correct && 'success'}
> >
{#if option.is_correct} {#if option.is_correct}
<CheckmarkFilled24 class="carbon-icon" /> <CheckmarkFilledIcon size={24} class="carbon-icon" />
{:else} {:else}
<CheckmarkOutline24 class="carbon-icon" /> <CheckmarkOutlineIcon size={24} class="carbon-icon" />
{/if} {/if}
</IconButton> </IconButton>
</div> </div>
@@ -332,7 +330,7 @@
variant={VARIANTS.OUTLINED} variant={VARIANTS.OUTLINED}
onClick={handleAddOption(question.id)} onClick={handleAddOption(question.id)}
> >
<AddFilled24 class="carbon-icon" /> <AddFilledIcon size={24} class="carbon-icon" />
<p class="dark:text-white ml-2">Add option</p> <p class="dark:text-white ml-2">Add option</p>
</PrimaryButton> </PrimaryButton>
</div> </div>
@@ -1,12 +1,12 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import Modal from '../../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import Select from '../../../../Form/Select.svelte'; import Select from '$lib/components/Form/Select.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '../../../../PrimaryButton/constants'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import Preview from './Preview.svelte'; import Preview from './Preview.svelte';
import { SELECTABLE_STATUS } from './constants'; import { SELECTABLE_STATUS } from './constants';
import { snackbarStore } from '../../../../Snackbar/store'; import { snackbarStore } from '$lib/components/Snackbar/store';
export let open = false; export let open = false;
export let onClose = () => {}; export let onClose = () => {};
@@ -1,11 +1,11 @@
<script lang="ts"> <script lang="ts">
import { dndzone } from 'svelte-dnd-action'; import { dndzone } from 'svelte-dnd-action';
import CheckboxCheckedFilled16 from 'carbon-icons-svelte/lib/CheckboxCheckedFilled16'; import CheckboxCheckedFilledIcon from 'carbon-icons-svelte/lib/CheckboxCheckedFilled.svelte';
import RadioButtonChecked16 from 'carbon-icons-svelte/lib/RadioButtonChecked16'; import RadioButtonCheckedIcon from 'carbon-icons-svelte/lib/RadioButtonChecked.svelte';
import TextAlignJustify16 from 'carbon-icons-svelte/lib/TextAlignJustify16'; import TextAlignJustifyIcon from 'carbon-icons-svelte/lib/TextAlignJustify.svelte';
import { flip } from 'svelte/animate'; 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 { questionnaireOrder, questionnaire } from '../store/exercise';
import { filterOutDeleted } from './functions'; import { filterOutDeleted } from './functions';
@@ -77,11 +77,11 @@
class="flex items-center rounded-md p-4 border border-blue-600" class="flex items-center rounded-md p-4 border border-blue-600"
> >
{#if item.type === 1} {#if item.type === 1}
<RadioButtonChecked16 class="carbon-icon active" /> <RadioButtonCheckedIcon size={16} class="carbon-icon active" />
{:else if item.type === 2} {:else if item.type === 2}
<CheckboxCheckedFilled16 class="carbon-icon active" /> <CheckboxCheckedFilledIcon size={16} class="carbon-icon active" />
{:else} {:else}
<TextAlignJustify16 class="carbon-icon active" /> <TextAlignJustifyIcon size={16} class="carbon-icon active" />
{/if} {/if}
{` ${item.name}`} {` ${item.name}`}
</div> </div>
@@ -1,8 +1,8 @@
<script> <script>
import RadioQuestion from '../../../../Question/RadioQuestion/index.svelte'; import RadioQuestion from '$lib/components/Question/RadioQuestion/index.svelte';
import CheckboxQuestion from '../../../../Question/CheckboxQuestion/index.svelte'; import CheckboxQuestion from '$lib/components/Question/CheckboxQuestion/index.svelte';
import TextareaQuestion from '../../../../Question/TextareaQuestion/index.svelte'; import TextareaQuestion from '$lib/components/Question/TextareaQuestion/index.svelte';
import { QUESTION_TYPE } from '../../../../Question/constants'; import { QUESTION_TYPE } from '$lib/components/Question/constants';
import { getPropsForQuestion } from './functions'; import { getPropsForQuestion } from './functions';
export let questions = []; export let questions = [];
@@ -1,24 +1,28 @@
<script> <script>
import marked from 'marked'; import { marked } from 'marked';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { group, course } from '../../../store'; import { group, course } from '$lib/components/Course/store';
import { questionnaire } from '../store/exercise'; import { questionnaire } from '../store/exercise';
import { questionnaireMetaData } from '../store/answers'; import { questionnaireMetaData } from '../store/answers';
import Preview from './Preview.svelte'; import Preview from './Preview.svelte';
import RadioQuestion from '../../../../Question/RadioQuestion/index.svelte'; import RadioQuestion from '$lib/components/Question/RadioQuestion/index.svelte';
import CheckboxQuestion from '../../../../Question/CheckboxQuestion/index.svelte'; import CheckboxQuestion from '$lib/components/Question/CheckboxQuestion/index.svelte';
import TextareaQuestion from '../../../../Question/TextareaQuestion/index.svelte'; import TextareaQuestion from '$lib/components/Question/TextareaQuestion/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import RoleBasedSecurity from '../../../../RoleBasedSecurity/index.svelte'; import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import Progress from '../../../../Progress/index.svelte'; import Progress from '$lib/components/Progress/index.svelte';
import { removeDuplicate } from '../../../../../utils/functions/removeDuplicate'; import { removeDuplicate } from '$lib/utils/functions/removeDuplicate';
import { QUESTION_TYPE } from '../../../../Question/constants'; import { QUESTION_TYPE } from '$lib/components/Question/constants';
import { STATUS } from './constants'; import { STATUS } from './constants';
import { getPropsForQuestion, filterOutDeleted } from './functions'; import { getPropsForQuestion, filterOutDeleted } from './functions';
import { formatAnswers, getGroupMemberId } from '../../../function'; import {
import { submitExercise } from '../../../../../utils/services/courses'; formatAnswers,
import { fetchSubmission } from '../../../../../utils/services/submissions'; getGroupMemberId,
import { profile } from '../../../../../utils/store/user'; } 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 preview;
export let exerciseId; export let exerciseId;
@@ -183,7 +187,7 @@
> >
<h3 class="dark:text-white text-2xl"> <h3 class="dark:text-white text-2xl">
No questions added. <br /> No questions added. <br />
<RoleBasedSecurity allowedRoles="[1,2]"> <RoleBasedSecurity allowedRoles={[1, 2]}>
Click the <span class="text-blue-700">Edit</span> button to add. Click the <span class="text-blue-700">Edit</span> button to add.
</RoleBasedSecurity> </RoleBasedSecurity>
</h3> </h3>
@@ -1,5 +1,5 @@
import { QUESTION_TYPE } from '../../../../Question/constants'; import { QUESTION_TYPE } from '$lib/components/Question/constants';
import { toggleConfetti } from '../../../../Confetti/store'; import { toggleConfetti } from '$lib/components/Confetti/store';
export const isAnswerCorrect = (options, answer) => { export const isAnswerCorrect = (options, answer) => {
return options.some((option) => option.is_correct && option.value === answer); return options.some((option) => option.is_correct && option.value === answer);
@@ -1,11 +1,10 @@
<script> <script>
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
import AddAlt32 from 'carbon-icons-svelte/lib/AddAlt32'; import AddAltIcon from 'carbon-icons-svelte/lib/AddAlt.svelte';
// import Delete32 from 'carbon-icons-svelte/lib/Delete32'; import TableIcon from 'carbon-icons-svelte/lib/Table.svelte';
import Table32 from 'carbon-icons-svelte/lib/Table32'; import SettingsIcon from 'carbon-icons-svelte/lib/Settings.svelte';
import Settings32 from 'carbon-icons-svelte/lib/Settings32'; import ViewIcon from 'carbon-icons-svelte/lib/View.svelte';
import View32 from 'carbon-icons-svelte/lib/View32'; import ViewFilledIcon from 'carbon-icons-svelte/lib/ViewFilled.svelte';
import ViewFilled32 from 'carbon-icons-svelte/lib/ViewFilled32';
import { import {
handleAddQuestion, handleAddQuestion,
questionnaire, questionnaire,
@@ -13,15 +12,15 @@
reset, reset,
questionnaireOrder, questionnaireOrder,
} from '../store/exercise'; } from '../store/exercise';
import PrimaryButton from '../../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import PageBody from '../../../../PageBody/index.svelte'; import PageBody from '$lib/components/PageBody/index.svelte';
import IconButton from '../../../../IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
import RoleBasedSecurity from '../../../../RoleBasedSecurity/index.svelte'; import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import ViewMode from './ViewMode.svelte'; import ViewMode from './ViewMode.svelte';
import EditMode from './EditMode.svelte'; import EditMode from './EditMode.svelte';
import MODES from '../../../../../utils/constants/mode.js'; import MODES from '$lib/utils/constants/mode.js';
import { VARIANTS } from '../../../../PrimaryButton/constants'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { upsertExercise } from '../../../../../utils/services/courses'; import { upsertExercise } from '$lib/utils/services/courses';
export let exerciseId; export let exerciseId;
export let refetchExercise = () => {}; export let refetchExercise = () => {};
@@ -71,7 +70,7 @@
<PageBody padding="px-4"> <PageBody padding="px-4">
<svelte:fragment slot="header"> <svelte:fragment slot="header">
<div class="flex items-center"> <div class="flex items-center">
<RoleBasedSecurity allowedRoles="[1,2]"> <RoleBasedSecurity allowedRoles={[1, 2]}>
<PrimaryButton <PrimaryButton
className="mr-2" className="mr-2"
variant={VARIANTS.CONTAINED} variant={VARIANTS.CONTAINED}
@@ -96,9 +95,9 @@
contained={true} contained={true}
> >
{#if preview} {#if preview}
<ViewFilled32 class="carbon-icon" /> <ViewFilledIcon size={32} class="carbon-icon" />
{:else} {:else}
<View32 class="carbon-icon" /> <ViewIcon size={32} class="carbon-icon" />
{/if} {/if}
</IconButton> </IconButton>
{/if} {/if}
@@ -110,19 +109,19 @@
onClick={handleAddQuestion} onClick={handleAddQuestion}
toolTipProps={{ title: 'Add question', direction: 'bottom' }} toolTipProps={{ title: 'Add question', direction: 'bottom' }}
> >
<AddAlt32 class="carbon-icon" /> <AddAltIcon size={32} class="carbon-icon" />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => ($questionnaireOrder.open = true)} onClick={() => ($questionnaireOrder.open = true)}
toolTipProps={{ title: 'Order questionnaire', direction: 'bottom' }} toolTipProps={{ title: 'Order questionnaire', direction: 'bottom' }}
> >
<Table32 class="carbon-icon" /> <TableIcon size={32} class="carbon-icon" />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => (editDescription = true)} onClick={() => (editDescription = true)}
toolTipProps={{ title: 'Edit description', direction: 'bottom' }} toolTipProps={{ title: 'Edit description', direction: 'bottom' }}
> >
<Settings32 class="carbon-icon" /> <SettingsIcon size={32} class="carbon-icon" />
</IconButton> </IconButton>
<!-- <IconButton <!-- <IconButton
@@ -1,19 +1,19 @@
<script> <script>
import { goto } from '@sapper/app'; import { goto } from '$app/navigation';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import AudioConsole32 from 'carbon-icons-svelte/lib/AudioConsole32'; import AudioConsoleIcon from 'carbon-icons-svelte/lib/AudioConsole.svelte';
import Box from '../../../../Box/index.svelte'; import Box from '$lib/components/Box/index.svelte';
import { Moon } from 'svelte-loading-spinners'; import { Moon } from 'svelte-loading-spinners';
import Backdrop from '../../../../Backdrop/index.svelte'; import Backdrop from '$lib/components/Backdrop/index.svelte';
import PrimaryButton from '../../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import RoleBasedSecurity from '../../../../RoleBasedSecurity/index.svelte'; import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import PageBody from '../../../../PageBody/index.svelte'; import PageBody from '$lib/components/PageBody/index.svelte';
import Modal from '../../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import TextField from '../../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import Exercise from '../Exercise/index.svelte'; import Exercise from '../Exercise/index.svelte';
import { supabase } from '../../../../../utils/functions/supabase'; import { supabase } from '$lib/utils/functions/supabase';
import { createExercise } from '../../../../../utils/services/courses'; import { createExercise } from '$lib/utils/services/courses';
import { QUESTION_TYPES } from '../../../../Question/constants'; import { QUESTION_TYPES } from '$lib/components/Question/constants';
import { lesson } from '../store/lessons'; import { lesson } from '../store/lessons';
import { questionnaire, isQuestionnaireFetching } from '../store/exercise'; import { questionnaire, isQuestionnaireFetching } from '../store/exercise';
@@ -70,7 +70,7 @@
isFetching = true; isFetching = true;
isQuestionnaireFetching.update(() => true); isQuestionnaireFetching.update(() => true);
const { data } = await supabase let { data, error } = await supabase
.from('exercise') .from('exercise')
.select( .select(
` `
@@ -85,6 +85,10 @@
.eq('id', exerciseId) .eq('id', exerciseId)
.single(); .single();
if (error) {
return;
}
if (data && Array.isArray(data.questions)) { if (data && Array.isArray(data.questions)) {
// Need to set the question type inorder for the select in the questionnaire builder to match // Need to set the question type inorder for the select in the questionnaire builder to match
data.questions.forEach((question) => { data.questions.forEach((question) => {
@@ -94,8 +98,10 @@
return question; return question;
}); });
data.questions = data.questions.sort((a, b) => a.order - b.order); data.questions = data.questions.sort((a, b) => a.order - b.order);
} else { } else if (data) {
data.questions = []; data.questions = [];
} else {
data = {};
} }
data.is_title_dirty = false; data.is_title_dirty = false;
@@ -156,7 +162,7 @@
<PageBody> <PageBody>
<slot:fragment slot="header"> <slot:fragment slot="header">
<RoleBasedSecurity allowedRoles="[1,2]"> <RoleBasedSecurity allowedRoles={[1, 2]}>
<PrimaryButton <PrimaryButton
className="mr-2" className="mr-2"
label="Add" label="Add"
@@ -176,7 +182,7 @@
</a> </a>
{:else} {:else}
<Box> <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"> <h3 class="text-3xl text-gray-500 dark:text-white">
No Exercise Added No Exercise Added
</h3> </h3>
@@ -1,13 +1,13 @@
<script> <script>
import MODES from '../../../../../utils/constants/mode.js'; import MODES from '$lib/utils/constants/mode.js';
import { formatYoutubeVideo } from '../../../../../utils/functions/formatYoutubeVideo'; import { formatYoutubeVideo } from '$lib/utils/functions/formatYoutubeVideo';
import Tabs from '../../../../Tabs/index.svelte'; import Tabs from '$lib/components/Tabs/index.svelte';
import TabContent from '../../../../TabContent/index.svelte'; import TabContent from '$lib/components/TabContent/index.svelte';
import MarkdownRender from '../../../../MarkdownRender/index.svelte'; import MarkdownRender from '$lib/components/MarkdownRender/index.svelte';
import Box from '../../../../Box/index.svelte'; import Box from '$lib/components/Box/index.svelte';
import EditContent from '../../../../EditContent/index.svelte'; import EditContent from '$lib/components/EditContent/index.svelte';
import TextField from '../../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import { import {
lesson, lesson,
handleUpdateLessonMaterials, handleUpdateLessonMaterials,
@@ -2,9 +2,9 @@ import { writable } from 'svelte/store';
import { import {
QUESTION_TEMPLATE, QUESTION_TEMPLATE,
QUESTION_TYPE, QUESTION_TYPE,
} from '../../../../Question/constants'; } from '$lib/components/Question/constants';
import { questionnaireMetaData } from './answers'; import { questionnaireMetaData } from './answers';
import { isUUID } from '../../../../../utils/functions/isUUID'; import { isUUID } from '$lib/utils/functions/isUUID';
export const isQuestionnaireFetching = writable(false); export const isQuestionnaireFetching = writable(false);
export const deleteConfirmation = writable({ open: 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 { import {
createLesson, createLesson,
updateLesson, updateLesson,
deleteLesson, 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 lessons: Writable<Lesson[]> = writable([]);
export const lesson = writable({ export const lesson = writable({
@@ -1,5 +1,5 @@
<script> <script>
import CaretSortDown20 from 'carbon-icons-svelte/lib/CaretSortDown20'; import CaretSortDownIcon from 'carbon-icons-svelte/lib/CaretSortDown.svelte';
let isExpanded = true; let isExpanded = true;
export let handleClick = () => {}; export let handleClick = () => {};
@@ -22,7 +22,8 @@
on:click={onClick} on:click={onClick}
> >
{#if !hideSortIcon} {#if !hideSortIcon}
<CaretSortDown20 <CaretSortDownIcon
size={20}
class="carbon-icon-sort {isExpanded ? '' : 'carbon-icon-minimize'}" class="carbon-icon-sort {isExpanded ? '' : 'carbon-icon-minimize'}"
/> />
{/if} {/if}
@@ -1,39 +1,39 @@
<script> <script>
import { onMount } from 'svelte'; 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 hotkeys from 'hotkeys-js';
import Home32 from 'carbon-icons-svelte/lib/Home32'; import HomeIcon from 'carbon-icons-svelte/lib/Home.svelte';
import CheckmarkFilled20 from 'carbon-icons-svelte/lib/CheckmarkFilled20'; import CheckmarkFilledIcon from 'carbon-icons-svelte/lib/CheckmarkFilled.svelte';
import Settings20 from 'carbon-icons-svelte/lib/Settings20'; import SettingsIcon from 'carbon-icons-svelte/lib/Settings.svelte';
import ChevronLeft16 from 'carbon-icons-svelte/lib/ChevronLeft16'; import ChevronLeftIcon from 'carbon-icons-svelte/lib/ChevronLeft.svelte';
import ChevronRight16 from 'carbon-icons-svelte/lib/ChevronRight16'; import ChevronRightIcon from 'carbon-icons-svelte/lib/ChevronRight.svelte';
import NavExpandable from './NavExpandable.svelte'; import NavExpandable from './NavExpandable.svelte';
import PageNav from '../../../PageNav/index.svelte'; import PageNav from '$lib/components/PageNav/index.svelte';
import IconButton from '../../../IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
import Avatar from '../../../Avatar/index.svelte'; import Avatar from '$lib/components/Avatar/index.svelte';
import { import {
getNavItemRoute, getNavItemRoute,
getLessonsRoute, getLessonsRoute,
getLectureNo, 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 Settings from '../Settings/index.svelte';
import { settingsDialog } from '../Settings/store'; import { settingsDialog } from '../Settings/store';
import { lessons } from '../Lesson/store/lessons'; import { lessons } from '../Lesson/store/lessons';
import { course } from '../../store'; import { course } from '$lib/components/Course/store';
import { updateCourse } from '../../../../utils/services/courses'; import { updateCourse } from '$lib/utils/services/courses';
import { profile } from '../../../../utils/store/user'; import { profile } from '$lib/utils/store/user';
import { currentOrg, currentOrgPath } from '../../../../utils/store/org'; import { currentOrgPath } from '$lib/utils/store/org';
import { isMobile } from '../../../../utils/store/useMobile'; import { isMobile } from '$lib/utils/store/useMobile';
import { browser } from '$app/environment';
// export let lessonId; // export let lessonId;
export let path; export let path;
export let isStudent = null; export let isStudent = null;
let show = null; let show = null;
const { page } = stores();
function handleMainGroupClick(href) { function handleMainGroupClick(href) {
return () => { return () => {
if ($isMobile) { if ($isMobile) {
@@ -47,7 +47,7 @@
function getHref(item) { function getHref(item) {
return item.to; return item.to;
// return item.is_complete ? item.to : path || $page.path // return item.is_complete ? item.to : path || $page.url.pathname
} }
function handleSaveTitle() { function handleSaveTitle() {
@@ -79,7 +79,7 @@
$: handleMobileChange($isMobile); $: handleMobileChange($isMobile);
$: { $: {
if (process.browser && show !== null) { if (browser) {
localStorage.setItem('hideCourseNav', `${!show}`); localStorage.setItem('hideCourseNav', `${!show}`);
} }
} }
@@ -154,11 +154,11 @@
<Avatar src={$course.logo} /> <Avatar src={$course.logo} />
</slot:fragment> </slot:fragment>
<slot:fragment slot="widget"> <slot:fragment slot="widget">
<RoleBasedSecurity allowedRoles="[1,2]"> <RoleBasedSecurity allowedRoles={[1, 2]}>
<IconButton <IconButton
onClick={() => ($settingsDialog.open = !$settingsDialog.open)} onClick={() => ($settingsDialog.open = !$settingsDialog.open)}
> >
<Settings20 class="carbon-icon" /> <SettingsIcon size={20} class="carbon-icon" />
</IconButton> </IconButton>
</RoleBasedSecurity> </RoleBasedSecurity>
</slot:fragment> </slot:fragment>
@@ -169,20 +169,20 @@
<NavExpandable <NavExpandable
label={navItem.label} label={navItem.label}
handleClick={handleMainGroupClick(navItem.to)} handleClick={handleMainGroupClick(navItem.to)}
isGroupActive={(path || $page.path) === navItem.to} isGroupActive={(path || $page.url.pathname) === navItem.to}
hideSortIcon={navItem.hideSortIcon} hideSortIcon={navItem.hideSortIcon}
> >
{#if navItem.isLecture} {#if navItem.isLecture}
{#each $lessons as item, index} {#each $lessons as item, index}
<a <a
class="item flex items-center {( class="item flex items-center {(
path || $page.path path || $page.url.pathname
).includes(item.id) && 'active'} pl-7 py-3 {isStudent && ).includes(item.id) && 'active'} pl-7 py-3 {isStudent &&
!item.is_complete !item.is_complete
? 'cursor-not-allowed' ? 'cursor-not-allowed'
: ''}" : ''}"
href={isStudent && !item.is_complete href={isStudent && !item.is_complete
? $page.path ? $page.url.pathname
: getLessonsRoute($course.id, item.id)} : getLessonsRoute($course.id, item.id)}
on:click={() => { on:click={() => {
if ($isMobile) { if ($isMobile) {
@@ -196,7 +196,7 @@
<span>{item.title}</span> <span>{item.title}</span>
{#if item.is_complete} {#if item.is_complete}
<span class="ml-2 success"> <span class="ml-2 success">
<CheckmarkFilled20 class="carbon-icon" /> <CheckmarkFilledIcon size={20} class="carbon-icon" />
</span> </span>
{:else} {:else}
<span class="text-md ml-2">🔒</span> <span class="text-md ml-2">🔒</span>
@@ -217,7 +217,7 @@
onClick={() => goto(`${$currentOrgPath}/courses`)} onClick={() => goto(`${$currentOrgPath}/courses`)}
buttonClassName="mx-3" buttonClassName="mx-3"
> >
<Home32 class="carbon-icon" /> <HomeIcon size={32} class="carbon-icon" />
</IconButton> </IconButton>
<a class="block mx-3" href={`/profile/${$profile.id}`}> <a class="block mx-3" href={`/profile/${$profile.id}`}>
<Avatar src={$profile.avatar_url} name={$profile.username} /> <Avatar src={$profile.avatar_url} name={$profile.username} />
@@ -240,9 +240,9 @@
}} }}
> >
{#if show} {#if show}
<ChevronLeft16 /> <ChevronLeftIcon size={16} />
{:else} {:else}
<ChevronRight16 /> <ChevronRightIcon size={16} />
{/if} {/if}
</IconButton> </IconButton>
</div> </div>
@@ -1,8 +1,8 @@
<script> <script>
import Modal from '../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '../../../PrimaryButton/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'; import { deleteMemberModal } from './store';
export let email; export let email;
@@ -1,15 +1,12 @@
<script> <script>
import Modal from '../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import TextArea from '../../../Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import { ROLE } from '../../../../utils/constants/roles'; import { ROLE } from '$lib/utils/constants/roles';
import { import { addGroupMember, fetchGroup } from '$lib/utils/services/courses';
addGroupMember,
fetchGroup,
} from '../../../../utils/services/courses';
import { invitationModal, resetForm } from './store'; import { invitationModal, resetForm } from './store';
import { validateForm } from '../../../Courses/functions'; import { validateForm } from '$lib/components/Courses/functions';
import { course, setCourse } from '../../store'; import { course, setCourse } from '$lib/components/Course/store';
let errors = { let errors = {
emails: '', emails: '',
@@ -1,18 +1,15 @@
<script> <script>
import { goto } from '@sapper/app'; import { goto } from '$app/navigation';
import Modal from '../../../Modal/index.svelte'; import Modal from '$lib/components/Modal/index.svelte';
import TextField from '../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import TextArea from '../../../Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import PrimaryButton from '../../../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import UploadImage from '../../../UploadImage/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 { settingsDialog } from './store';
import { course } from '../../store'; import { course } from '$lib/components/Course/store';
import { import { updateCourse, deleteCourse } from '$lib/utils/services/courses';
updateCourse,
deleteCourse,
} from '../../../../utils/services/courses';
let shouldDelete = false; let shouldDelete = false;
let avatar; let avatar;
@@ -1,13 +1,13 @@
<script> <script>
import marked from 'marked'; import { marked } from 'marked';
import RoleBasedSecurity from '../RoleBasedSecurity/index.svelte'; import RoleBasedSecurity from '../RoleBasedSecurity/index.svelte';
import PageNav from '../PageNav/index.svelte'; import PageNav from '../PageNav/index.svelte';
import MODES from '../../utils/constants/mode'; import MODES from '$lib/utils/constants/mode';
import PrimaryButton from '../PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import PageBody from '../PageBody/index.svelte'; import PageBody from '../PageBody/index.svelte';
import EditContent from '../EditContent/index.svelte'; import EditContent from '../EditContent/index.svelte';
import { course } from './store'; import { course } from './store';
import { updateCourse } from '../../utils/services/courses'; import { updateCourse } from '$lib/utils/services/courses';
let mode = MODES.view; let mode = MODES.view;
let isDirty = false; let isDirty = false;
@@ -27,7 +27,7 @@
<PageNav title="Overview" disableSticky={true}> <PageNav title="Overview" disableSticky={true}>
<svelte:fragment slot="widget"> <svelte:fragment slot="widget">
<RoleBasedSecurity allowedRoles="[1,2]"> <RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="flex items-center"> <div class="flex items-center">
<PrimaryButton <PrimaryButton
className="mr-2" 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'; import { lessons } from './components/Lesson/store/lessons';
//@ts-ignore //@ts-ignore
import { ROLE } from '../../utils/constants/roles'; import { ROLE } from '$lib/utils/constants/roles';
import type { Course } from '../../utils/types'; import type { Course } from '$lib/utils/types';
export const course: Writable<Course> = writable({ export const course: Writable<Course> = writable({
id: '', id: '',
@@ -1,14 +1,14 @@
<script> <script>
import { Moon } from 'svelte-loading-spinners'; import { Moon } from 'svelte-loading-spinners';
import Navigation from '../Course/components/Navigation/index.svelte'; 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 { lessons, lesson } from '../Course/components/Lesson/store/lessons';
// import { questionnaire } from '../Course/components/Lesson/Exercise/store/exercise'; // import { questionnaire } from '../Course/components/Lesson/Exercise/store/exercise';
// import { questionnaireMetaData } from '../Course/components/Lesson/store/answers'; // import { questionnaireMetaData } from '../Course/components/Lesson/store/answers';
import { course, group } from '../Course/store'; import { course, group } from '../Course/store';
import Confetti from '../Confetti/index.svelte'; import Confetti from '../Confetti/index.svelte';
import { isMobile } from '../../utils/store/useMobile'; import { isMobile } from '$lib/utils/store/useMobile';
import { profile } from '../../utils/store/user'; import { profile } from '$lib/utils/store/user';
export let path = ''; export let path = '';
export let isExercisePage = false; export let isExercisePage = false;
@@ -1,8 +1,8 @@
<script> <script>
import ChevronLeft16 from 'carbon-icons-svelte/lib/ChevronLeft16'; import ChevronLeftIcon from 'carbon-icons-svelte/lib/ChevronLeft.svelte';
import ChevronRight16 from 'carbon-icons-svelte/lib/ChevronRight16'; import ChevronRightIcon from 'carbon-icons-svelte/lib/ChevronRight.svelte';
import { isMobile } from '../../../../utils/store/useMobile'; import { isMobile } from '$lib/utils/store/useMobile';
import IconButton from '../../../IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
export let show = true; export let show = true;
</script> </script>
@@ -31,9 +31,9 @@
}} }}
> >
{#if show} {#if show}
<ChevronLeft16 /> <ChevronLeftIcon size={16} />
{:else} {:else}
<ChevronRight16 /> <ChevronRightIcon size={16} />
{/if} {/if}
</IconButton> </IconButton>
</div> </div>
@@ -2,7 +2,7 @@
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set'; import set from 'lodash/set';
import get from 'lodash/get'; import get from 'lodash/get';
import TextEditor from '../../../TextEditor/index.svelte'; import TextEditor from '$lib/components/TextEditor/index.svelte';
export let course; export let course;
</script> </script>
@@ -2,7 +2,7 @@
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set'; import set from 'lodash/set';
import get from 'lodash/get'; import get from 'lodash/get';
import TextEditor from '../../../TextEditor/index.svelte'; import TextEditor from '$lib/components/TextEditor/index.svelte';
export let course; export let course;
</script> </script>
@@ -1,6 +1,6 @@
<script> <script>
import TextArea from '../../../Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import TextField from '../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
export let course = {}; export let course = {};
</script> </script>
@@ -3,10 +3,10 @@
import set from 'lodash/set'; import set from 'lodash/set';
import get from 'lodash/get'; import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import TextArea from '../../../Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import TextField from '../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import UploadImage from '../../../UploadImage/index.svelte'; import UploadImage from '$lib/components/UploadImage/index.svelte';
import { uploadAvatar } from '../../../../utils/services/courses'; import { uploadAvatar } from '$lib/utils/services/courses';
export let course = {}; export let course = {};
let name; let name;
@@ -4,8 +4,8 @@
import get from 'lodash/get'; import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import { Toggle } from 'carbon-components-svelte'; import { Toggle } from 'carbon-components-svelte';
import TextEditor from '../../../TextEditor/index.svelte'; import TextEditor from '$lib/components/TextEditor/index.svelte';
import TextField from '../../../Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
export let course = {}; export let course = {};
@@ -2,7 +2,7 @@
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set'; import set from 'lodash/set';
import get from 'lodash/get'; import get from 'lodash/get';
import TextEditor from '../../../TextEditor/index.svelte'; import TextEditor from '$lib/components/TextEditor/index.svelte';
export let course; export let course;
</script> </script>

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