From 72f615523786e1bda714895e0de6f5ce95b3aa0a Mon Sep 17 00:00:00 2001 From: jakeaturner Date: Tue, 30 Jul 2024 11:12:19 -0700 Subject: [PATCH] fix(VideoStreaming): embed codes --- client/src/api.ts | 4 +- .../components/FilesManager/FilesManager.tsx | 60 ++++++++++++++++--- server/api/projectfiles.ts | 22 +++---- 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/client/src/api.ts b/client/src/api.ts index f1ff5b09..d50c88bf 100644 --- a/client/src/api.ts +++ b/client/src/api.ts @@ -204,7 +204,9 @@ class API { async getProjectFileEmbedHTML(projectID: string, fileID: string) { const res = await axios.get< { - embedHTML: string; + media_id: string; + embed_url: string; + embed_html: string; } & ConductorBaseResponse >(`/project/${projectID}/files/${fileID}/embed`); return res; diff --git a/client/src/components/FilesManager/FilesManager.tsx b/client/src/components/FilesManager/FilesManager.tsx index 6fb00452..94a100b3 100644 --- a/client/src/components/FilesManager/FilesManager.tsx +++ b/client/src/components/FilesManager/FilesManager.tsx @@ -409,23 +409,54 @@ const FilesManager: React.FC = ({ } } - async function handleGetEmbedCode(videoID: string) { + async function handleGetEmbedCode( + videoID: string, + type: "html" | "url" | "adapt" = "html" + ): Promise { try { const res = await api.getProjectFileEmbedHTML(projectID, videoID); if (res.data.err) { throw new Error(res.data.errMsg); } - const code = res.data.embedHTML; - await copyToClipboard( - code, - "Embed code copied to clipboard. NOTE: This code is only valid on libretexts.org or libretexts.net domains." - ); + if (!res.data.embed_html || !res.data.embed_url) { + throw new Error("Unable to get embed code. Please try again later."); + } + + const code = + type === "html" + ? res.data.embed_html + : type === "url" + ? res.data.embed_url + : res.data.media_id; + + return code; } catch (err) { handleGlobalError(err); + return null; } } + async function handleCopyEmbedCode(videoID: string) { + const code = await handleGetEmbedCode(videoID); + if (!code) return; + await copyToClipboard( + code, + "Embed code copied to clipboard. NOTE: This code is only valid on libretexts.org or libretexts.net domains." + ); + } + + async function handleCopyToADAPT(videoID: string) { + const mediaID = await handleGetEmbedCode(videoID, "adapt"); + if (!mediaID) return; + + const text = `conductor-media/${mediaID}`; + await copyToClipboard( + text, + "URL copied to clipboard. Paste this URL into the ADAPT editor to embed the video." + ); + } + /** * Updates state with the a new directory to bring into view. * @@ -478,7 +509,7 @@ const FilesManager: React.FC = ({ } - direction="right" + direction="left" > {canViewDetails && ( @@ -518,7 +549,20 @@ const FilesManager: React.FC = ({ icon="code" text="Embed" onClick={async () => { - await handleGetEmbedCode(item.fileID); + await handleCopyEmbedCode(item.fileID); + }} + /> + )} + {item.storageType === "file" && + item.isVideo && + item.videoStorageID && + item.access === "public" && + projectVisibility === "public" && ( + { + await handleCopyToADAPT(item.fileID); }} /> )} diff --git a/server/api/projectfiles.ts b/server/api/projectfiles.ts index 7d730d6c..db3559eb 100644 --- a/server/api/projectfiles.ts +++ b/server/api/projectfiles.ts @@ -565,7 +565,7 @@ async function getProjectFolderContents( const projectID = req.params.projectID; const folderID = req.params.folderID; const publicOnly = req.query.publicOnly; - + const project = await Project.findOne({ projectID }).lean(); if (!project) { return conductor404Err(res); @@ -647,7 +647,7 @@ async function getProjectFile( [fileID], req.user?.decoded.uuid ? undefined : true, req.user?.decoded.uuid - ) + ); const file = files && files?.length > 0 ? files[0] : null; @@ -922,7 +922,8 @@ async function updateProjectFileAccess( } /* Update file and any children */ - const entriesToUpdate: (RawProjectFileInterface | ProjectFileInterface)[] = []; + const entriesToUpdate: (RawProjectFileInterface | ProjectFileInterface)[] = + []; const findChildEntriesToUpdate = (parentID: string) => { files.forEach((obj) => { @@ -1244,20 +1245,15 @@ async function getProjectFileEmbedHTML( }); } - const ENDPOINT = `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_STREAM_ACCOUNT_ID}/stream/${file.videoStorageID}/embed`; - const cloudFlareRes = await axios.get(ENDPOINT, { - headers: { - Authorization: `Bearer ${process.env.CLOUDFLARE_STREAM_API_TOKEN}`, - }, - }); + const ENDPOINT = `https://customer-${process.env.CLOUDFLARE_STREAM_CUSTOMER_CODE}.cloudflarestream.com/${file.videoStorageID}/iframe`; - if (cloudFlareRes.status !== 200) { - throw new Error("Failed to retrieve embed HTML"); - } + const HTML = ``; return res.send({ err: false, - embedHTML: cloudFlareRes.data, + media_id: file.videoStorageID, + embed_url: ENDPOINT, + embed_html: HTML, }); } catch (err) { debugError(err);