Merge branch 'main' into CLASSROOMIO-T-84

This commit is contained in:
tunny17
2023-08-11 12:39:37 +01:00
31 changed files with 525 additions and 251 deletions
+8 -2
View File
@@ -39,7 +39,7 @@
import '../app.postcss';
let supabase = getSupabase();
let path = $page.url.pathname.replace('/', '');
let path = $page.url?.pathname?.replace('/', '');
let theme = 'white';
let skipAuth = false;
@@ -261,7 +261,7 @@
};
});
$: path = $page.url.pathname.replace('/', '');
$: path = $page.url?.pathname?.replace('/', '');
$: theme = $appStore.isDark ? 'g100' : 'white';
$: setOrgBasedOnUrl($page.url.host);
</script>
@@ -384,4 +384,10 @@
:global(.dark .bx--search-close:hover > svg) {
fill: #fff;
}
:global(.plyr__controls) {
background: url(/logo-192.png) 99% 70% no-repeat,
linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.5)) !important;
background-size: 50px auto, auto !important;
}
</style>
+42
View File
@@ -0,0 +1,42 @@
import { json } from '@sveltejs/kit';
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
import {
CLOUDFLARE_ACCESS_KEY,
CLOUDFLARE_SECRET_ACCESS_KEY,
CLOUDFLARE_ACCOUNT_ID,
CLOUDFLARE_PUBLIC_ACCOUNT_ID,
MUSE_API_KEY
} from '$env/static/private';
const S3 = new S3Client({
region: 'auto',
endpoint: `https://${CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: CLOUDFLARE_ACCESS_KEY,
secretAccessKey: CLOUDFLARE_SECRET_ACCESS_KEY
}
});
const downloadTranscript = async () => {};
const uploadTranscriptToS3 = async () => {};
export async function GET({ url }) {
const museFid = url.searchParams.get('museFid');
console.log('museFid');
// check the transcript table and see if we find a record
// if we find one
// check if downloaded = true
// if true
// return the transcript
// if false
// download the transcript from muse
// upload it to S3
// return the transcript
// if we dont
return json({ success: true, museFid });
}
+2 -1
View File
@@ -3,6 +3,7 @@
import CourseContainer from '$lib/components/CourseContainer/index.svelte';
import { setCourse } from '$lib/components/Course/store';
import { fetchCourse } from '$lib/utils/services/courses';
import { browser } from '$app/environment';
export let data;
const { courseId } = data;
@@ -10,7 +11,7 @@
let prevCourseId = '';
async function onCourseIdChange(courseId = '') {
if (!courseId || prevCourseId === courseId) return;
if (!courseId || prevCourseId === courseId || !browser) return;
const { data: _data } = await fetchCourse(courseId);
+2 -2
View File
@@ -135,12 +135,12 @@
{#each $lessons as lesson (lesson.id)}
<div
bind:this={ref}
class="sm:h-48 md:h-40 lg:h-32 relative m-auto rounded-md border-2 border-gray-100 py-3 px-5 mb-4 flex items-center dark:bg-gray-700"
class="sm:h-48 md:h-40 lg:h-32 relative m-auto rounded-md border-2 border-gray-200 py-3 px-5 mb-4 flex items-center dark:bg-gray-700"
>
<div class="mr-5">
<TextChip
value={getLessonOrder(lesson.id)}
size="xl"
size="sm"
shape="rounded-full"
className="bg-blue-200 text-blue-600 text-xs"
/>
@@ -1,13 +0,0 @@
export const load = ({ params = { id: '' } }) => {
const { id: courseId, lessonParams = [] } = params;
const splitparams = lessonParams.split('/');
const [lessonId, exerciseRouteName, exerciseId] = splitparams;
return {
courseId,
lessonId,
exerciseRouteName,
exerciseId,
isMaterialsTabActive: !exerciseRouteName
};
};
@@ -0,0 +1,167 @@
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
import FormData from 'form-data';
import axios from 'axios';
import { fail } from '@sveltejs/kit';
import genUniqueId from '$lib/utils/functions/genUniqueId.js';
import { getSupabase } from '$lib/utils/functions/supabase';
import {
CLOUDFLARE_ACCESS_KEY,
CLOUDFLARE_SECRET_ACCESS_KEY,
CLOUDFLARE_ACCOUNT_ID,
CLOUDFLARE_PUBLIC_ACCOUNT_ID,
MUSE_API_KEY
} from '$env/static/private';
// Set the runtime to edge for best performance
export const config = {
runtime: 'edge'
};
const S3 = new S3Client({
region: 'auto',
endpoint: `https://${CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: CLOUDFLARE_ACCESS_KEY,
secretAccessKey: CLOUDFLARE_SECRET_ACCESS_KEY
}
});
const supabase = getSupabase();
const uploadToMuse = (s3Data, fileName, lessonId, fileUrl) => {
try {
const form = new FormData();
form.append('file', s3Data, fileName);
axios({
method: 'POST',
url: 'https://api.muse.ai/api/files/upload',
data: form,
maxContentLength: Infinity,
maxBodyLength: Infinity,
headers: {
Key: MUSE_API_KEY
}
})
.then(async function (response) {
console.log('Upload to muse complete', response.data);
const { data: lesson } = await supabase
.from('lesson')
.select(`*`)
.eq('id', lessonId)
.single();
if (lesson) {
// Add Muse response to metadata
const videos = lesson.videos.map((v) => {
if (v.link === fileUrl) {
console.log('matches');
v.metadata = JSON.parse(JSON.stringify(response.data));
}
return v;
});
const { error, data } = await supabase
.from('lesson')
.update({ videos })
.eq('id', lessonId)
.select();
if (error) {
console.log('Error updating lesson', error);
}
console.log('update data', data);
}
})
.catch(function (error) {
console.log('Upload to Muse failed', error);
});
} catch (error) {
console.log('Upload to Muse failed', error);
}
};
export const load = ({ params = { id: '' } }) => {
const { id: courseId, lessonParams = [] } = params;
const splitparams = lessonParams.split('/');
const [lessonId, exerciseRouteName, exerciseId] = splitparams;
return {
courseId,
lessonId,
exerciseRouteName,
exerciseId,
isMaterialsTabActive: !exerciseRouteName
};
};
export const actions = {
create: async ({ request }) => {
const formData = Object.fromEntries(await request.formData());
console.log('formData', formData);
if (!formData.file?.name || formData.file?.name === 'undefined') {
return fail(400, {
success: false,
message: 'You must provide a file to upload'
});
}
if (formData.file?.size > 20 * 1024 * 1024) {
return fail(400, {
success: false,
type: 'FILE_TOO_LARGE',
message: 'File is too large'
});
}
const { file, lessonId } = formData;
console.log('file', file);
console.log('lessonId', lessonId);
const stream = await file.arrayBuffer();
const fileName = `${genUniqueId()}-${file.name}`;
const params = {
Bucket: 'videos',
Key: fileName,
Body: stream,
ContentLength: stream.length
};
console.log('params', params);
let upload;
const fileUrl = `https://pub-${CLOUDFLARE_PUBLIC_ACCOUNT_ID}.r2.dev/${fileName}`;
try {
upload = await S3.send(new PutObjectCommand(params));
// process data.
} catch (error) {
// error handling.
const { requestId, cfId, extendedRequestId } = error.$$metadata;
console.error('Error uploading file');
console.log({ requestId, cfId, extendedRequestId });
} finally {
// finally.
console.log('File upload complete', upload);
console.log('\n\nInitilizing Muse Request');
const data = await S3.send(
new GetObjectCommand({
Bucket: 'videos',
Key: fileName
})
);
// console.log('GetObjectCommand', data);
uploadToMuse(data.Body, file.name, lessonId, fileUrl);
}
return {
success: true,
url: fileUrl,
message: 'Uploaded successfully'
};
}
};
@@ -12,11 +12,17 @@
import Exercises from '$lib/components/Course/components/Lesson/Exercises/index.svelte';
import MODES from '$lib/utils/constants/mode.js';
import { setCourse, course } from '$lib/components/Course/store';
import { lesson, handleSaveLesson } from '$lib/components/Course/components/Lesson/store/lessons';
import {
lesson,
handleSaveLesson,
uploadCourseVideoStore
} from '$lib/components/Course/components/Lesson/store/lessons';
import { browser } from '$app/environment';
export let data;
export let form;
let path = '';
let mode = MODES.view;
let prevMode = '';
@@ -68,12 +74,14 @@
mode = mode === MODES.edit ? MODES.view : MODES.edit;
}
$: path = $page.url.pathname.replace(/\/exercises[\/ 0-9 a-z -]*/, '');
$: path = $page.url?.pathname?.replace(/\/exercises[\/ 0-9 a-z -]*/, '');
$: if (data.courseId && browser) {
mode = MODES.view;
fetchReqData(data.lessonId);
}
$: $uploadCourseVideoStore.formRes = form;
</script>
<CourseContainer {isFetching} {path} isExercisePage={!data.isMaterialsTabActive && data.exerciseId}>
@@ -112,7 +120,7 @@
<Exercises lessonId={data.lessonId} exerciseId={data.exerciseId} path={`${path}/exercises`} />
{:else if !!data.lessonId}
<PageBody>
<Materials lessonId={data.lessonId} {mode} {prevMode} {toggleMode} />
<Materials lessonId={data.lessonId} {mode} {prevMode} />
<div class="w-full flex flex-row-reverse">
<PrimaryButton
@@ -248,7 +248,7 @@
<div class="flex items-center w-full">
{#each sections as { id, title, items }, idx (id)}
<div
class="section rounded-md bg-gray-100 dark:bg-gray-700 border border-gray-50 p-3 h-80 mr-3 overflow-hidden"
class="section rounded-md bg-gray-100 dark:bg-gray-800 border border-gray-50 p-3 h-80 mr-3 overflow-hidden"
animate:flip={{ duration: flipDurationMs }}
>
<div class="flex items-center mb-2">
@@ -293,7 +293,7 @@
</a>
<a
class="flex items-center no-underline hover:underline text-black my-2"
href="{$page.url.pathname.replace('submissions', 'lessons')}/{item.lesson
href="{$page.url?.pathname?.replace('submissions', 'lessons')}/{item.lesson
.id}/exercises/{item.exercise.id}"
>
<p class="dark:text-white text-grey text-sm">