feat: support embed of generic links

This commit is contained in:
Rotimi Best
2024-04-04 14:38:18 +01:00
parent 2553d42dae
commit 136e057954
6 changed files with 131 additions and 7 deletions
@@ -0,0 +1,80 @@
<script>
import { CopyButton, Tag } from 'carbon-components-svelte';
import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import { lesson, isLessonDirty } from '$lib/components/Course/components/Lesson/store/lessons';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
let genericLinks = '';
let error = '';
function getVideoUrls(urls = '') {
return (urls || '').split(',').filter((url) => !!url.trim());
}
function addVideo() {
const links = getVideoUrls(genericLinks);
const validLinks = links.filter(isValidLink);
if (validLinks.length === 0) {
error = 'Invalid link(s)';
} else {
const existingLinks = $lesson?.materials?.videos || [];
$lesson.materials.videos = [
...existingLinks,
...validLinks.map((link = '') => ({
type: 'generic',
link,
metadata: {}
}))
];
genericLinks = '';
error = '';
}
}
function isValidLink(link = '') {
const linkRegex = /^(https?:\/\/)?(www\.)?([a-zA-Z]+\.com\/)([a-zA-Z0-9_-]+)/;
return linkRegex.test(link.trim());
}
function removeVideo(index = 0) {
$lesson.materials.videos = $lesson.materials.videos.filter((v, i) => i !== index);
}
</script>
<div class="w-full flex items-{error ? 'center' : 'end'} justify-between gap-5">
<TextField
label="Embed link"
bind:value={genericLinks}
className="flex-1 text-left "
inputClassName="text-sm"
onChange={() => ($isLessonDirty = true)}
placeholder="https://www.videoplayer.com/"
errorMessage={error}
/>
<PrimaryButton label="Add Video" className="rounded-md" onClick={addVideo} />
</div>
<p class="mt-4 pl-2 text-sm">
Videos added: <strong>
{$lesson?.materials?.videos.filter((v) => v.type === 'generic').length || 0}
</strong>
</p>
<div class="">
{#each $lesson?.materials?.videos as video, index}
{#if video.type === 'generic'}
<div class="flex items-center gap-1">
<Tag type="blue">
{video.link}
</Tag>
<CopyButton text={video.link} feedback="Copied to clipboard" />
<IconButton value="delete-video" onClick={() => removeVideo(index)}>
<TrashCanIcon size={16} class="carbon-icon dark:text-white" />
</IconButton>
</div>
{/if}
{/each}
</div>
@@ -1,6 +1,7 @@
<script>
import YoutubeVideo from './YoutubeVideo.svelte';
import LocalVideo from './LocalVideo.svelte';
import EmbedLink from './EmbedLink.svelte';
import * as CONSTANTS from './constants';
export let lessonId = '';
@@ -37,6 +38,8 @@
<main class="w-full h-full">
{#if currentTab === 1}
<YoutubeVideo />
{:else if currentTab === 2}
<EmbedLink />
{:else}
<LocalVideo {lessonId} />
{/if}
@@ -1,5 +1,7 @@
import Link from 'carbon-icons-svelte/lib/Link.svelte';
import Video from 'carbon-icons-svelte/lib/Video.svelte';
import DirectLink from 'carbon-icons-svelte/lib/DirectLink.svelte';
export const videoTabs = [
{
value: 1,
@@ -8,7 +10,12 @@ export const videoTabs = [
},
{
value: 2,
title: 'Video',
title: 'Embed Link',
icon: DirectLink
},
{
value: 3,
title: 'Upload',
icon: Video
}
];
@@ -35,6 +35,17 @@
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
/>
{:else if video.type === 'generic'}
<iframe
width="100%"
height="569"
class="iframe"
src={video.link}
title="Embeded Video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
/>
{:else if video.metadata?.svid}
<div style="position:relative;padding-bottom:51.416579%">
<iframe
@@ -42,6 +42,7 @@
export let prevMode = '';
export let lessonId = '';
export let isSaving = false;
export let isStudent = false;
export let toggleMode = () => {};
let lessonTitle = '';
@@ -343,6 +344,17 @@
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
/>
{:else if video.type === 'generic'}
<iframe
width="100%"
height="569"
class="iframe"
src={video.link}
title="Embeded Video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
/>
{:else if video.metadata?.svid}
<div style="position:relative;padding-bottom:51.416579%">
<iframe
@@ -381,10 +393,12 @@
<h3 class="text-xl font-normal dark:text-white py-2">
No note, video or slide added for this lesson yet
</h3>
<p class="text-sm text-center font-normal py-2">
Share your knowledge with your students by creating engaging content<br />
Start by clicking on <strong>Get started</strong> button.
</p>
<PrimaryButton label="Get started" className="rounded-md" onClick={toggleMode} />
{#if !isStudent}
<p class="text-sm text-center font-normal py-2">
Share your knowledge with your students by creating engaging content<br />
Start by clicking on <strong>Get started</strong> button.
</p>
<PrimaryButton label="Get started" className="rounded-md" onClick={toggleMode} />
{/if}
</Box>
{/if}
@@ -298,7 +298,16 @@
width="lg:w-full xl:w-11/12"
className="overflow-x-hidden"
>
<Materials lessonId={data.lessonId} {mode} {prevMode} {toggleMode} bind:isSaving />
<!-- Shows Lesson Note / Slides / Video -->
<Materials
lessonId={data.lessonId}
{mode}
{prevMode}
{toggleMode}
bind:isSaving
{isStudent}
/>
{#if isStudent}
<div class="w-full hidden lg:flex flex-row-reverse mt-10">
<PrimaryButton