feat: move landing page videos to cloudfare (#253)
* moved videos to cloudfare * add custom domain * add border to iframe --------- Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
PUBLIC_SUPABASE_ANON_KEY=
|
PUBLIC_SUPABASE_ANON_KEY=
|
||||||
PUBLIC_SUPABASE_URL=
|
PUBLIC_SUPABASE_URL=
|
||||||
|
|
||||||
|
# https://cdn.example.com
|
||||||
|
CLOUDFLARE_BUCKET_DOMAIN=
|
||||||
|
|
||||||
CLOUDFLARE_TOKEN_VALUE=
|
CLOUDFLARE_TOKEN_VALUE=
|
||||||
CLOUDFLARE_ACCESS_KEY=
|
CLOUDFLARE_ACCESS_KEY=
|
||||||
CLOUDFLARE_SECRET_ACCESS_KEY=
|
CLOUDFLARE_SECRET_ACCESS_KEY=
|
||||||
|
|||||||
@@ -42,3 +42,7 @@ app.get('/', (req, res) => {
|
|||||||
app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
console.log(`ClassroomIO Backend listening on port ${port}!`);
|
console.log(`ClassroomIO Backend listening on port ${port}!`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
process.on('uncaughtException', (err) => {
|
||||||
|
console.error('Uncaught error, err');
|
||||||
|
});
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ const unlinkAsync = promisify(fs.unlink);
|
|||||||
|
|
||||||
const { Upload } = require('@aws-sdk/lib-storage');
|
const { Upload } = require('@aws-sdk/lib-storage');
|
||||||
const {
|
const {
|
||||||
S3Client,
|
S3Client
|
||||||
PutObjectCommand
|
// PutObjectCommand
|
||||||
// GetObjectCommand,
|
// GetObjectCommand,
|
||||||
} = require('@aws-sdk/client-s3');
|
} = require('@aws-sdk/client-s3');
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ const genUniqueId = require('../utils/genUniqueId');
|
|||||||
const upload = require('../utils/upload');
|
const upload = require('../utils/upload');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
CLOUDFLARE_BUCKET_DOMAIN,
|
||||||
CLOUDFLARE_ACCESS_KEY,
|
CLOUDFLARE_ACCESS_KEY,
|
||||||
CLOUDFLARE_SECRET_ACCESS_KEY,
|
CLOUDFLARE_SECRET_ACCESS_KEY,
|
||||||
CLOUDFLARE_ACCOUNT_ID,
|
CLOUDFLARE_ACCOUNT_ID,
|
||||||
@@ -75,7 +76,10 @@ router.post('/', upload.single('videoFile'), async (req, res) => {
|
|||||||
|
|
||||||
const fileName = `${genUniqueId()}-${file.originalname.split(' ').join('-')}`;
|
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 = {
|
let metadata = {
|
||||||
sizeInMb: fileSizeInMegabytes
|
sizeInMb: fileSizeInMegabytes
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
taglineIcon="simplified"
|
taglineIcon="simplified"
|
||||||
title="Advanced Course Management"
|
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."
|
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}
|
rightToLeft={true}
|
||||||
/>
|
/>
|
||||||
<Section
|
<Section
|
||||||
@@ -19,16 +19,15 @@
|
|||||||
title="Customization at its Core"
|
title="Customization at its Core"
|
||||||
description="ClassroomIO offers organizations the ability to tailor our LMS to their specific requirements. With our customizable features, you can create a personalized learning environment that aligns with your organization's goals"
|
description="ClassroomIO offers organizations the ability to tailor our LMS to their specific requirements. With our customizable features, you can create a personalized learning environment that aligns with your organization's goals"
|
||||||
rightToLeft={true}
|
rightToLeft={true}
|
||||||
video="/lms-customization.mp4"
|
video="https://brand.cdn.clsrio.com/lms-customization.mp4"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Section
|
<Section
|
||||||
id="collaboration"
|
id="collaboration"
|
||||||
tagline="Collaboration"
|
tagline="Collaboration"
|
||||||
taglineIcon="collaboration"
|
taglineIcon="collaboration"
|
||||||
title="Your Knowledge Base"
|
title="Your Knowledge Base"
|
||||||
description="Our platform includes a forum-like feature where students and teachers can ask and answer questions, creating a collaborative learning environment. This fosters engagement and knowledge sharing among the community"
|
description="Our platform includes a forum-like feature where students and teachers can ask and answer questions, creating a collaborative learning environment. This fosters engagement and knowledge sharing among the community"
|
||||||
video="/community.mp4"
|
video="https://brand.cdn.clsrio.com/community.mp4"
|
||||||
rightToLeft={true}
|
rightToLeft={true}
|
||||||
/>
|
/>
|
||||||
<Section
|
<Section
|
||||||
@@ -38,7 +37,7 @@
|
|||||||
title="AI Integration for Lesson Planning"
|
title="AI Integration for Lesson Planning"
|
||||||
description="Our platform integrates AI to simplify lesson outline generation, streamline lesson planning and spark creative ideas. With ClassroomIO, educators can focus on what matters most: teaching."
|
description="Our platform integrates AI to simplify lesson outline generation, streamline lesson planning and spark creative ideas. With ClassroomIO, educators can focus on what matters most: teaching."
|
||||||
rightToLeft={true}
|
rightToLeft={true}
|
||||||
video="/ai-lesson.mp4"
|
video="https://brand.cdn.clsrio.com/ai-lesson.mp4"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- body section 5 -->
|
<!-- body section 5 -->
|
||||||
|
|||||||
@@ -29,10 +29,7 @@
|
|||||||
playsinline
|
playsinline
|
||||||
preload="auto"
|
preload="auto"
|
||||||
>
|
>
|
||||||
<source
|
<source src="https://video.cdn.clsrio.com/student-dashboard.mp4" type="video/mp4" />
|
||||||
src="https://pub-bd38ff7251aa402a93762181a947f7ea.r2.dev/student-dashboard.mp4"
|
|
||||||
type="video/mp4"
|
|
||||||
/>
|
|
||||||
<track kind="captions" />
|
<track kind="captions" />
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -97,6 +97,20 @@ h6 {
|
|||||||
color: #fff !important;
|
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 {
|
code {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|||||||
-12
@@ -69,15 +69,3 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
|
||||||
.iframe {
|
|
||||||
width: 100%;
|
|
||||||
height: 450px;
|
|
||||||
}
|
|
||||||
@media (max-width: 760px) {
|
|
||||||
.iframe {
|
|
||||||
height: 209px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { PUBLIC_SERVER_URL } from '$env/static/public';
|
import { PUBLIC_SERVER_URL } from '$env/static/public';
|
||||||
|
|
||||||
|
|
||||||
var win, output, textarea;
|
var win, output, textarea;
|
||||||
|
|
||||||
// Follow this guide to get source code: https://editor.codecogs.com/docs/3-Tiny_MCE_v6.php
|
// 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) {
|
tinymce.PluginManager.add('eqneditor', function (editor, url) {
|
||||||
// Load necessary javascript for editor from CodeCogs
|
// Load necessary javascript for editor from CodeCogs
|
||||||
var sl = new tinymce.dom.ScriptLoader();
|
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();
|
var loaded = sl.loadQueue();
|
||||||
|
|
||||||
// Load custom CSS
|
// 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(
|
editor.ui.registry.addIcon(
|
||||||
'logo',
|
'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:
|
// 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
|
// https://latex.codecogs.com/svg.image
|
||||||
|
|
||||||
// 1. Get only the URL in the img tag generated by codecogs library
|
// 1. Get only the URL in the img tag generated by codecogs library
|
||||||
const srcRegex = /<img[^>]+src\s*=\s*['"]([^'"]+)['"][^>]*>/i;
|
const srcRegex = /<img[^>]+src\s*=\s*['"]([^'"]+)['"][^>]*>/i;
|
||||||
const srcMatch = content.match(srcRegex);
|
const srcMatch = content.match(srcRegex);
|
||||||
|
|
||||||
if (srcMatch) {
|
if (srcMatch) {
|
||||||
// 2. Point the formula to our server
|
// 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);
|
const url = srcMatch[1]?.replaceAll('https://latex.codecogs.com/svg.image', customAPI);
|
||||||
|
|
||||||
// 3. Fetch the HTML from the server
|
// 3. Fetch the HTML from the server
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const html = await response.text();
|
const html = await response.text();
|
||||||
|
|
||||||
// 4. Set the content to the html
|
// 4. Set the content to the html
|
||||||
content = `<p>${html}</p><p> </p>`;
|
content = `<p>${html}</p><p> </p>`;
|
||||||
} else {
|
} 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);
|
tinymce.activeEditor.execCommand('mceInsertContent', false, content);
|
||||||
|
|||||||
@@ -17,6 +17,15 @@ In this guide I will be showing you how to set up a local student dashboard that
|
|||||||
|
|
||||||
### Demo
|
### Demo
|
||||||
|
|
||||||
<video width="100%" controls>
|
<div className="nx-w-full nx-flex nx-items-center nx-justify-center">
|
||||||
<source src={`${process.env.imagePath}/local-student-dashboard-setup.mp4`} type="video/mp4" />
|
<iframe
|
||||||
</video>
|
width="560"
|
||||||
|
height="315"
|
||||||
|
src="https://youtu.be/QGTnK39xexs"
|
||||||
|
title="YouTube video player"
|
||||||
|
frameborder="0"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||||
|
className="nx-my-4 nx-rounded-md"
|
||||||
|
allowfullscreen
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user