From 0638420e38b916ddeeb84995a9bd81ec4b0b9739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Abell=C3=A1?= Date: Tue, 23 Jan 2024 14:36:37 -0300 Subject: [PATCH 1/3] [NG23-60] Support Youtube links on learn page --- assets/src/hooks/video_player.ts | 57 ++++++++++++++++--- .../live/delivery/student/learn_live.ex | 15 ++++- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/assets/src/hooks/video_player.ts b/assets/src/hooks/video_player.ts index 6ba68dbf043..893db0079ce 100644 --- a/assets/src/hooks/video_player.ts +++ b/assets/src/hooks/video_player.ts @@ -1,19 +1,58 @@ export const VideoPlayer = { mounted() { - const video = document.getElementById('student_learn_video') as HTMLVideoElement; + const cloudVideo = document.getElementById('cloud_video') as HTMLVideoElement; + const youtubeIframe = document.getElementById('youtube_video') as HTMLIFrameElement; + const videoWrapper = document.getElementById('student_video_wrapper') as HTMLDivElement; window.addEventListener('phx:play_video', (e) => { - video.classList.remove('hidden'); - video.requestFullscreen(); - video.setAttribute('src', (e as CustomEvent).detail.video_url); - video.play(); + const videoUrl = (e as CustomEvent).detail.video_url; + + videoWrapper.classList.remove('hidden'); + if (videoUrl.includes('youtube.com') || videoUrl.includes('youtu.be')) { + youtubeIframe.src = this.convertToEmbedURL(videoUrl); + youtubeIframe.requestFullscreen(); + } else { + cloudVideo.requestFullscreen(); + cloudVideo.setAttribute('src', videoUrl); + cloudVideo.play(); + } }); - video?.addEventListener('fullscreenchange', () => { + /** + The convertToEmbedURL function is designed to convert various YouTube URL formats into a standardized embeddable URL format. This is crucial for embedding YouTube videos within an iframe. + + The regular expression used below is crafted to identify and extract the video ID from different YouTube URL formats. It is versatile enough to handle standard and shortened YouTube URLs. + Handled Formats: + - Standard: https://www.youtube.com/watch?v=VIDEO_ID + - Shortened: https://youtu.be/VIDEO_ID + - Embed: https://www.youtube.com/embed/VIDEO_ID + + The expression consists of two main parts: + - The first part (youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=) captures the various URL structures preceding the video ID. + = The second part ([^#\&\?]*).*, which corresponds to match[2], captures the actual video ID. + + YouTube video IDs typically have a length of exactly 11 characters. This standardization is a part of YouTube's design. + The check match[2].length == 11 is employed to ensure that the extracted string is indeed a valid YouTube video ID. + */ + this.convertToEmbedURL = (url) => { + const regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; + const match = url.match(regExp); + const videoId = match && match[2].length == 11 ? match[2] : null; + if (videoId) { + return `https://www.youtube.com/embed/${videoId}?autoplay=1`; + } else { + return url; + } + }; + + document.addEventListener('fullscreenchange', () => { if (!document.fullscreenElement) { - video.pause(); - video.classList.add('hidden'); - video.currentTime = 0; + cloudVideo.pause(); + cloudVideo.currentTime = 0; + + youtubeIframe.src = ''; + + videoWrapper.classList.add('hidden'); } }); }, diff --git a/lib/oli_web/live/delivery/student/learn_live.ex b/lib/oli_web/live/delivery/student/learn_live.ex index efe740a223f..d63e152e040 100644 --- a/lib/oli_web/live/delivery/student/learn_live.ex +++ b/lib/oli_web/live/delivery/student/learn_live.ex @@ -319,9 +319,7 @@ defmodule OliWeb.Delivery.Student.LearnLive do def render(assigns) do ~H"""
- + <.video_player /> <.unit :for={unit <- @full_hierarchy["children"]} unit={unit} @@ -1068,6 +1066,17 @@ defmodule OliWeb.Delivery.Student.LearnLive do """ end + def video_player(assigns) do + ~H""" + + """ + end + _docp = """ Currently the intro_content for a revision does not support h1 tags. So, if there is no

tag in the content then we need to add an additional margin From 55b8316767b6dc2246bf68b6b77e8ecb65d01db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Abell=C3=A1?= Date: Tue, 23 Jan 2024 15:44:02 -0300 Subject: [PATCH 2/3] [NG23-60] Clear Section cache data after importing a project CSV --- lib/oli_web/live/import/csv_import_view.ex | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/oli_web/live/import/csv_import_view.ex b/lib/oli_web/live/import/csv_import_view.ex index c6930b6fa34..a9017973af0 100644 --- a/lib/oli_web/live/import/csv_import_view.ex +++ b/lib/oli_web/live/import/csv_import_view.ex @@ -32,6 +32,7 @@ defmodule OliWeb.Import.CSVImportView do socket ) do author = Repo.get(Author, author_id) + project = Oli.Authoring.Course.get_project_by_slug(project_slug) ingest_file = ingest_file(author) if File.exists?(ingest_file) do @@ -46,6 +47,7 @@ defmodule OliWeb.Import.CSVImportView do assign(socket, breadcrumbs: set_breadcrumbs(), author: author, + project: project, finished: false, results: [] )} @@ -173,6 +175,10 @@ defmodule OliWeb.Import.CSVImportView do end def handle_info({:finished}, socket) do + socket.assigns.project + |> Oli.Delivery.Sections.get_sections_by_base_project() + |> Enum.each(&Oli.Delivery.Sections.SectionCache.clear(&1.slug)) + {:noreply, assign(socket, finished: true From 7c5444a27bda94d8b3ce076d7789b7e24ca993d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Abell=C3=A1?= Date: Wed, 24 Jan 2024 10:25:15 -0300 Subject: [PATCH 3/3] [NG23-60] Fix regexp issues --- assets/src/hooks/video_player.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/src/hooks/video_player.ts b/assets/src/hooks/video_player.ts index 893db0079ce..ea3ed587577 100644 --- a/assets/src/hooks/video_player.ts +++ b/assets/src/hooks/video_player.ts @@ -34,8 +34,8 @@ export const VideoPlayer = { YouTube video IDs typically have a length of exactly 11 characters. This standardization is a part of YouTube's design. The check match[2].length == 11 is employed to ensure that the extracted string is indeed a valid YouTube video ID. */ - this.convertToEmbedURL = (url) => { - const regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; + this.convertToEmbedURL = (url: string) => { + const regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; const match = url.match(regExp); const videoId = match && match[2].length == 11 ? match[2] : null; if (videoId) {