From 42231b3ee111f6d379434f399a22cab4cf0ae7e5 Mon Sep 17 00:00:00 2001 From: Rotimi Best Date: Sun, 28 Jun 2026 22:21:05 +0100 Subject: [PATCH] fix: filter library videos in lesson with videos in the current lesson --- .../lesson/video/add-video-modal.svelte | 2 +- .../video/lesson-video-simple-card.svelte | 20 --------- .../lesson/video/library-video.svelte | 43 ++++++++++++++----- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/apps/dashboard/src/lib/features/course/components/lesson/video/add-video-modal.svelte b/apps/dashboard/src/lib/features/course/components/lesson/video/add-video-modal.svelte index 6251a787..98c589b5 100644 --- a/apps/dashboard/src/lib/features/course/components/lesson/video/add-video-modal.svelte +++ b/apps/dashboard/src/lib/features/course/components/lesson/video/add-video-modal.svelte @@ -45,7 +45,7 @@ {$t('course.navItem.lessons.materials.tabs.video.add_video.title')} - + {#each tabs as item (item.value)} - import * as Avatar from '@cio/ui/base/avatar'; import { Image } from '$features/ui'; import VideoIcon from '@lucide/svelte/icons/video'; import { ExternalLinkIcon, HoverableItem } from '@cio/ui/custom/moving-icons'; @@ -36,16 +35,6 @@ const isYoutubeWithLink = $derived(video.type === 'youtube' && !!video.link); - const courseLogoSrc = $derived.by(() => { - const raw = courseApi.course?.logo; - - if (typeof raw === 'string' && raw.trim().length > 0) { - return raw.trim(); - } - - return null; - }); - const channelLine = $derived.by(() => { const courseTitle = courseApi.course?.title?.trim(); @@ -104,15 +93,6 @@
- - {#if courseLogoSrc} - - {/if} - - - - -
diff --git a/apps/dashboard/src/lib/features/course/components/lesson/video/library-video.svelte b/apps/dashboard/src/lib/features/course/components/lesson/video/library-video.svelte index 253629c0..bc363688 100644 --- a/apps/dashboard/src/lib/features/course/components/lesson/video/library-video.svelte +++ b/apps/dashboard/src/lib/features/course/components/lesson/video/library-video.svelte @@ -3,6 +3,7 @@ import { Spinner } from '@cio/ui/base/spinner'; import { Empty } from '@cio/ui/custom/empty'; import { InputField } from '@cio/ui/custom/input-field'; + import VideoIcon from '@lucide/svelte/icons/video'; import { lessonApi } from '$features/course/api'; import { mediaApi } from '$features/media/api'; import type { OrganizationAsset } from '$features/media/utils'; @@ -21,10 +22,21 @@ let search = $state(''); let isLoading = $state(false); let addingAssetId = $state(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). + // Local copy so the fetch (which also backs the media manager page via the + // shared mediaApi.assets store) doesn't leak removals between surfaces. let assets = $state([]); + // Asset ids already attached to this lesson, so the library hides them. + const addedAssetIds = $derived( + new Set( + (lessonApi.lesson?.videos ?? []) + .map((video) => (video as { assetId?: string }).assetId) + .filter((id): id is string => Boolean(id)) + ) + ); + + const visibleAssets = $derived(assets.filter((asset) => !addedAssetIds.has(asset.id))); + async function loadLibrary() { isLoading = true; await mediaApi.listAssets({ @@ -53,7 +65,6 @@ } 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; @@ -65,7 +76,7 @@ }); -
+
- {:else if assets.length === 0} + {:else if visibleAssets.length === 0}

{$t('course.navItem.lessons.materials.tabs.video.add_video.no_library_videos')}

{:else}
- {#each assets as asset (asset.id)} + {#each visibleAssets as asset (asset.id)}
-
-

{asset.title || asset.storageKey || asset.id}

-

{asset.provider}

+
+
+ {#if asset.thumbnailUrl} + {asset.title + {:else} + + {/if} +
+
+

{asset.title || asset.storageKey || asset.id}

+

{asset.provider}

+