diff --git a/apps/backend/.env.example b/apps/backend/.env.example index fe12ec82..7a4c6e88 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -1,6 +1,9 @@ PUBLIC_SUPABASE_ANON_KEY= PUBLIC_SUPABASE_URL= +# https://cdn.example.com +CLOUDFLARE_BUCKET_DOMAIN= + CLOUDFLARE_TOKEN_VALUE= CLOUDFLARE_ACCESS_KEY= CLOUDFLARE_SECRET_ACCESS_KEY= diff --git a/apps/backend/server.js b/apps/backend/server.js index 90670aff..90886b4b 100644 --- a/apps/backend/server.js +++ b/apps/backend/server.js @@ -42,3 +42,7 @@ app.get('/', (req, res) => { app.listen(port, () => { console.log(`ClassroomIO Backend listening on port ${port}!`); }); + +process.on('uncaughtException', (err) => { + console.error('Uncaught error, err'); +}); diff --git a/apps/backend/src/routes/uploadVideo.js b/apps/backend/src/routes/uploadVideo.js index a98dc045..2acba3a7 100644 --- a/apps/backend/src/routes/uploadVideo.js +++ b/apps/backend/src/routes/uploadVideo.js @@ -8,8 +8,8 @@ const unlinkAsync = promisify(fs.unlink); const { Upload } = require('@aws-sdk/lib-storage'); const { - S3Client, - PutObjectCommand + S3Client + // PutObjectCommand // GetObjectCommand, } = require('@aws-sdk/client-s3'); @@ -19,6 +19,7 @@ const genUniqueId = require('../utils/genUniqueId'); const upload = require('../utils/upload'); const { + CLOUDFLARE_BUCKET_DOMAIN, CLOUDFLARE_ACCESS_KEY, CLOUDFLARE_SECRET_ACCESS_KEY, CLOUDFLARE_ACCOUNT_ID, @@ -75,7 +76,10 @@ router.post('/', upload.single('videoFile'), async (req, res) => { const fileName = `${genUniqueId()}-${file.originalname.split(' ').join('-')}`; - const fileUrl = `https://pub-${CLOUDFLARE_PUBLIC_ACCOUNT_ID}.r2.dev/${fileName}`; + const fileOrigin = + CLOUDFLARE_BUCKET_DOMAIN ?? `https://pub-${CLOUDFLARE_PUBLIC_ACCOUNT_ID}.r2.dev`; + + const fileUrl = `${fileOrigin}/${fileName}`; let metadata = { sizeInMb: fileSizeInMegabytes }; diff --git a/apps/backend/uploads/.empty b/apps/backend/uploads/.empty new file mode 100644 index 00000000..e69de29b diff --git a/apps/classroomio-com/src/lib/Body/Body.svelte b/apps/classroomio-com/src/lib/Body/Body.svelte index 2365e756..287fc56d 100644 --- a/apps/classroomio-com/src/lib/Body/Body.svelte +++ b/apps/classroomio-com/src/lib/Body/Body.svelte @@ -9,7 +9,7 @@ taglineIcon="simplified" title="Advanced Course Management" description="ClassroomIO simplifies teaching tasks, boosts the educational experience, and is beneficial for both educators and students, providing a user-friendly platform for assessment, grading, attendance, and scorebook management." - video="/course-management.mp4" + video="https://brand.cdn.clsrio.com/course-management.mp4" rightToLeft={true} />
-
diff --git a/apps/classroomio-com/src/lib/StudentDashboard/StudentDashboard.svelte b/apps/classroomio-com/src/lib/StudentDashboard/StudentDashboard.svelte index be5b1306..b38eb446 100644 --- a/apps/classroomio-com/src/lib/StudentDashboard/StudentDashboard.svelte +++ b/apps/classroomio-com/src/lib/StudentDashboard/StudentDashboard.svelte @@ -29,10 +29,7 @@ playsinline preload="auto" > - + diff --git a/apps/dashboard/src/app.postcss b/apps/dashboard/src/app.postcss index f9a5c7ff..dedecda9 100644 --- a/apps/dashboard/src/app.postcss +++ b/apps/dashboard/src/app.postcss @@ -97,6 +97,20 @@ h6 { color: #fff !important; } +iframe.iframe { + width: 100%; + max-width: 800px; + margin: 0 auto; + height: 450px; + border: 1px solid gray; + border-radius: 5px; +} +@media (max-width: 760px) { + iframe.iframe { + height: 209px; + } +} + code { white-space: pre-wrap; } diff --git a/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/components/ComponentVideo.svelte b/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/components/ComponentVideo.svelte index b8f7795c..0d601b3a 100644 --- a/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/components/ComponentVideo.svelte +++ b/apps/dashboard/src/lib/components/Course/components/Lesson/Materials/components/ComponentVideo.svelte @@ -69,15 +69,3 @@ {/each} {/if} - - diff --git a/apps/dashboard/src/lib/utils/functions/tinymce/plugins.ts b/apps/dashboard/src/lib/utils/functions/tinymce/plugins.ts index 1199b570..d9a7d413 100644 --- a/apps/dashboard/src/lib/utils/functions/tinymce/plugins.ts +++ b/apps/dashboard/src/lib/utils/functions/tinymce/plugins.ts @@ -1,6 +1,5 @@ import { PUBLIC_SERVER_URL } from '$env/static/public'; - var win, output, textarea; // Follow this guide to get source code: https://editor.codecogs.com/docs/3-Tiny_MCE_v6.php @@ -8,11 +7,11 @@ export const addMathPlugin = (tinymce: any) => { tinymce.PluginManager.add('eqneditor', function (editor, url) { // Load necessary javascript for editor from CodeCogs var sl = new tinymce.dom.ScriptLoader(); - sl.add('https://pub-19b235c5098f4ff1a6b1099331c8d00e.r2.dev/eqneditor.api.min.js'); + sl.add('https://assets.cdn.clsrio.com/eqneditor.api.min.js'); var loaded = sl.loadQueue(); // Load custom CSS - tinymce.DOM.loadCSS('https://pub-19b235c5098f4ff1a6b1099331c8d00e.r2.dev/eqneditor_1.css'); + tinymce.DOM.loadCSS('https://assets.cdn.clsrio.com/eqneditor_1.css'); editor.ui.registry.addIcon( 'logo', @@ -90,24 +89,24 @@ export const addMathPlugin = (tinymce: any) => { // The generated content always points to https://latex.codecogs.com/svg.image, this means we have to always rely on their server to serve formulas. We have a dedicated endpoint for generating formulas on our backend service: GET `/katex`. We will need to manually update the URL in the generate HTML to point to our server: // https://latex.codecogs.com/svg.image - + // 1. Get only the URL in the img tag generated by codecogs library const srcRegex = /]+src\s*=\s*['"]([^'"]+)['"][^>]*>/i; const srcMatch = content.match(srcRegex); if (srcMatch) { // 2. Point the formula to our server - const customAPI = PUBLIC_SERVER_URL + '/katex' + const customAPI = PUBLIC_SERVER_URL + '/katex'; const url = srcMatch[1]?.replaceAll('https://latex.codecogs.com/svg.image', customAPI); // 3. Fetch the HTML from the server const response = await fetch(url); - const html = await response.text(); + const html = await response.text(); // 4. Set the content to the html content = `

${html}

 

`; } else { - console.error("No src attribute found in the img tag."); + console.error('No src attribute found in the img tag.'); } tinymce.activeEditor.execCommand('mceInsertContent', false, content); diff --git a/apps/docs/pages/contributor-guides/student-dashboard.mdx b/apps/docs/pages/contributor-guides/student-dashboard.mdx index 73a261ae..240c6bb5 100644 --- a/apps/docs/pages/contributor-guides/student-dashboard.mdx +++ b/apps/docs/pages/contributor-guides/student-dashboard.mdx @@ -17,6 +17,15 @@ In this guide I will be showing you how to set up a local student dashboard that ### Demo - +
+ +
diff --git a/apps/docs/public/local-student-dashboard-setup.mp4 b/apps/docs/public/local-student-dashboard-setup.mp4 deleted file mode 100644 index 35a89738..00000000 Binary files a/apps/docs/public/local-student-dashboard-setup.mp4 and /dev/null differ