fix: enable adding video from library to another lesson
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
import { classroomio } from '$lib/utils/services/api';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import { getBrowserTimezone, instantToZonedWallClock, zonedWallClockToInstant } from '$lib/utils/functions/date';
|
||||
import { getVideoTitle, isHlsUploadVideo, type LessonVideo } from './video/video-card-utils';
|
||||
import { getVideoTitle, type LessonVideo } from './video/video-card-utils';
|
||||
|
||||
type LessonCompletionPolicy = 'manual' | 'video_watch' | 'none';
|
||||
|
||||
@@ -328,9 +328,6 @@
|
||||
/>
|
||||
<Field.Label for={`watch-enforced-${video.assetId}`} class="font-normal">
|
||||
{getVideoTitle(video, index)}
|
||||
{#if isHlsUploadVideo(video)}
|
||||
<span class="ui:text-muted-foreground ml-1 text-xs">(HLS)</span>
|
||||
{/if}
|
||||
</Field.Label>
|
||||
</Field.Field>
|
||||
{/each}
|
||||
|
||||
+46
-22
@@ -1,10 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
import { Spinner } from '@cio/ui/base/spinner';
|
||||
import { Empty } from '@cio/ui/custom/empty';
|
||||
import { InputField } from '@cio/ui/custom/input-field';
|
||||
import { lessonApi } from '$features/course/api';
|
||||
import { mediaApi } from '$features/media/api';
|
||||
import type { OrganizationAsset } from '$features/media/utils';
|
||||
import { onMount } from 'svelte';
|
||||
import { flip } from 'svelte/animate';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { snackbar } from '$features/ui/snackbar/store';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
interface Props {
|
||||
@@ -15,10 +20,10 @@
|
||||
|
||||
let search = $state('');
|
||||
let isLoading = $state(false);
|
||||
|
||||
const assets = $derived(
|
||||
mediaApi.assets.filter((asset) => asset.kind === 'video' && (asset.status ?? 'active') !== 'archived')
|
||||
);
|
||||
let addingAssetId = $state<string | null>(null);
|
||||
// Local copy so adding a video swipes it out of this list without mutating the
|
||||
// shared mediaApi.assets store (which also backs the media manager page).
|
||||
let assets = $state<OrganizationAsset[]>([]);
|
||||
|
||||
async function loadLibrary() {
|
||||
isLoading = true;
|
||||
@@ -27,24 +32,32 @@
|
||||
limit: 100,
|
||||
search: search.trim() || undefined
|
||||
});
|
||||
assets = mediaApi.assets.filter((asset) => asset.kind === 'video' && (asset.status ?? 'active') !== 'archived');
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
async function addFromLibrary(asset: OrganizationAsset) {
|
||||
if (!lessonApi.lesson) return;
|
||||
|
||||
const position = Array.isArray(lessonApi.lesson.videos) ? lessonApi.lesson.videos.length : 0;
|
||||
const lessonVideo = await mediaApi.buildLessonVideoFromAsset(asset, {
|
||||
lessonId: lessonId || undefined,
|
||||
position,
|
||||
slotType: 'lesson_video'
|
||||
});
|
||||
addingAssetId = asset.id;
|
||||
try {
|
||||
const position = Array.isArray(lessonApi.lesson.videos) ? lessonApi.lesson.videos.length : 0;
|
||||
const lessonVideo = await mediaApi.buildLessonVideoFromAsset(asset, {
|
||||
lessonId: lessonId || undefined,
|
||||
position,
|
||||
slotType: 'lesson_video'
|
||||
});
|
||||
|
||||
if (!lessonVideo) {
|
||||
return;
|
||||
if (!lessonVideo) {
|
||||
return;
|
||||
}
|
||||
|
||||
lessonApi.updateLessonState('videos', [lessonVideo], { append: true });
|
||||
assets = assets.filter((item) => item.id !== asset.id);
|
||||
snackbar.success('snackbar.media_manager.added_to_lesson');
|
||||
} finally {
|
||||
addingAssetId = null;
|
||||
}
|
||||
|
||||
lessonApi.updateLessonState('videos', [lessonVideo], { append: true });
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
@@ -66,22 +79,33 @@
|
||||
</div>
|
||||
|
||||
{#if isLoading}
|
||||
<p class="ui:text-muted-foreground text-sm">
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.loading_library')}
|
||||
</p>
|
||||
<Empty
|
||||
description={$t('course.navItem.lessons.materials.tabs.video.add_video.loading_library')}
|
||||
icon={Spinner}
|
||||
class="ui:max-h-40 py-6"
|
||||
/>
|
||||
{:else if assets.length === 0}
|
||||
<p class="ui:text-muted-foreground text-sm">
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.no_library_videos')}
|
||||
</p>
|
||||
{:else}
|
||||
<div class="max-h-[360px] space-y-2 overflow-auto pr-1">
|
||||
<div class="max-h-[360px] space-y-2 overflow-x-hidden">
|
||||
{#each assets as asset (asset.id)}
|
||||
<div class="flex items-center justify-between rounded-md border p-3">
|
||||
<div class="min-w-0">
|
||||
<p class="truncate text-sm font-medium">{asset.title || asset.storageKey || asset.id}</p>
|
||||
<div
|
||||
class="flex items-center justify-between rounded-md border p-3"
|
||||
animate:flip={{ duration: 250 }}
|
||||
out:fly={{ x: -400, duration: 300 }}
|
||||
>
|
||||
<div class="max-w-md">
|
||||
<p class="truncate text-sm font-medium wrap-break-word">{asset.title || asset.storageKey || asset.id}</p>
|
||||
<p class="ui:text-muted-foreground text-xs">{asset.provider}</p>
|
||||
</div>
|
||||
<Button size="sm" onclick={() => addFromLibrary(asset)}>
|
||||
<Button
|
||||
size="sm"
|
||||
onclick={() => addFromLibrary(asset)}
|
||||
loading={addingAssetId === asset.id}
|
||||
disabled={addingAssetId !== null}
|
||||
>
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.add_from_library')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user