PageSourceSearch

https://vizuara.ai/assets/AdminCoursePreviewVideos-DZE7eIa4.js

js vizuara.ai collected 2026-10-05 13:15:09 UTC 15,045 bytes, 6 lines download raw bytes

1import{r as n,j as e}from"./vendor-react-hRGeXtCl.js";import{A as Pe,a as Be,b as Le,c as Ae,d as Ie,e as Re,f as Ge,g as Ue}from"./alert-dialog-D5ka6lT8.js";import{B as k}from"./badge-PzEDaj62.js";import{a1 as $e,a as Ve,B as Oe,c8 as Te,bn as qe,a9 as ze,aJ as re,bK as f,c9 as De,aP as ae,bb as ne,c1 as _e,b as p,L as j,R as Me,K as Ke,I as Fe,b2 as Qe,aV as He,bW as Je,ca as We,bp as Ye,b8 as Xe,ag as Ze,aS as es,ao as ss,a0 as ts,bO as O}from"./index-W8Ef7Ftb.js";import{C as T}from"./checkbox-226T8PBw.js";import{r as rs}from"./concurrency-BTXMcwmZ.js";import{u as as}from"./contentOperationsContext-I-lzF4gi.js";import{S as ie}from"./shuffle-2zF_c1Xh.js";import{C as ns}from"./circle-check-Mrx9LXan.js";import{C as is}from"./circle-x-Bz0hj5OP.js";import"./vendor-common-BosuxZz1.js";/**
2 * @license lucide-react v0.462.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const ls=$e("SquarePlay",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"m9 8 6 4-6 4Z",key:"f1r3lt"}]]);class z extends Error{constructor(d,h){super(h),this.code=d,this.name="PreviewVideoApiError"}}const le={async generate(o){const d=await Ve.getAuthHeaders(),h=await fetch(`${Oe}/generateCoursePreviewVideos`,{method:"POST",headers:{...d,"Content-Type":"application/json"},body:JSON.stringify(o)}),c=await h.json().catch(()=>null);if(!h.ok)throw new z((c==null?void 0:c.code)||"PIPELINE_ERROR",(c==null?void 0:c.message)||"Failed to generate preview videos.");return c}},oe=["","",""],os=3;function q(o){try{const d=new URL(o);return d.protocol==="https:"&&d.hostname==="player.mediadelivery.net"}catch{return!1}}function ds(o,d){return o?{label:`${o.videos.length} preview${o.videos.length===1?"":"s"}`,className:"border-green-200 bg-green-50 text-green-800",icon:"check"}:d!==void 0&&d>=3?{label:"Eligible",className:"border-yellow-200 bg-yellow-50 text-yellow-800",icon:"sparkles"}:{label:"Not generated",className:"border-red-200 bg-red-50 text-red-700",icon:"cross"}}function cs(o){try{const d=new URL(o);return d.searchParams.set("autoplay","false"),d.searchParams.set("muted","true"),d.toString()}catch{return o}}function ys(){const{selectedCourseId:o}=as(),[d]=Te(),h=qe(),[c,de]=n.useState([]),[ce,D]=n.useState(!0),[x,ue]=n.useState({}),[me,_]=n.useState(!0),[I,he]=n.useState(""),[E,xe]=n.useState("all"),[P,M]=n.useState(null),[v,b]=n.useState(new Set),[fe,K]=n.useState(new Set),[B,F]=n.useState(!1),[pe,Q]=n.useState({}),[R,H]=n.useState([]),[ge,J]=n.useState(!1),[y,W]=n.useState(oe),[L,Y]=n.useState(!1),[ve,G]=n.useState(!1),[U,X]=n.useState(!1);n.useEffect(()=>b(new Set),[o]);const m=c.find(s=>s.id===P),$=n.useCallback(async()=>{D(!0);try{const t=[...await ze.getAllCourses()].sort((r,a)=>{var i,l;return(((i=re(a.createdAt))==null?void 0:i.getTime())??0)-(((l=re(r.createdAt))==null?void 0:l.getTime())??0)});return de(t),t}catch{return f({title:"Could not load courses",variant:"destructive"}),[]}finally{D(!1)}},[]),g=n.useCallback(async()=>{_(!0);try{const s=await De.getAllCoursePreviewVideos();ue(s)}catch{f({title:"Could not load preview videos",variant:"destructive"})}finally{_(!1)}},[]);n.useEffect(()=>{$(),g()},[$,g]);const N=ce||me,Z=n.useRef(!1);n.useEffect(()=>{var t;if(N||Z.current)return;Z.current=!0;const s=d.get("courseId");s&&(M(s),(t=document.getElementById(`preview-course-${s}`))==null||t.scrollIntoView({behavior:"smooth",block:"center"}))},[N,d]),n.useEffect(()=>{H([]),W(oe),X(!1);const s=c.find(r=>r.id===P);if(!s)return;J(!0);const t=s.topics.flatMap(r=>r.items.filter(a=>a.type===ae.LESSON).map(a=>a.id));ne.getLessonsByIds([...new Set(t)]).then(r=>{const a=r.filter(i=>q(i.embedUrl));H(a),Q(i=>({...i,[s.id]:new Set(a.map(l=>l.embedUrl)).size}))}).finally(()=>J(!1))},[P]);const ee=new Set(y.filter(Boolean)),se=y.every(q)&&ee.size===3,we=n.useMemo(()=>new Set(y.filter(Boolean)),[y]),je=s=>{M(t=>t===s?null:s)},be=s=>{W(t=>{const r=[...t],a=r.indexOf(s.embedUrl);if(a>=0)r[a]="";else{const i=r.indexOf("");if(i<0)return f({description:"Remove one of the selected sources before adding another."}),t;r[i]=s.embedUrl}return r})},ye=async()=>
6{if(!(!m||!se)){G(!1),Y(!0);try{await le.generate({courseId:m.id,sourceVideos:y,replaceExistingBunnyVideos:U}),await h.invalidateQueries({queryKey:O.coursePreviewVideos(m.id)}),await g(),f({title:"Preview videos generated",description:"The course preview has been refreshed."})}catch(s){s instanceof z&&s.code==="PIPELINE_TIMEOUT"&&(await h.invalidateQueries({queryKey:O.coursePreviewVideos(m.id)}),await g()),f({title:s instanceof z&&s.code==="PIPELINE_TIMEOUT"?"Generation status is uncertain":"Generation failed",description:s instanceof Error?s.message:"Unable to generate preview videos.",variant:"destructive"})}finally{Y(!1)}}},Ne=async s=>{const t=s.topics.flatMap(l=>l.items.filter(w=>w.type===ae.LESSON).map(w=>w.id)),r=await ne.getLessonsByIds([...new Set(t)]),a=[...new Set(r.filter(l=>q(l.embedUrl)).map(l=>l.embedUrl))];return Q(l=>({...l,[s.id]:a.length})),a.length<3?null:[...a].sort(()=>Math.random()-.5).slice(0,3)},te=async s=>{K(t=>new Set(t).add(s.id));try{const t=await Ne(s);return t?(await le.generate({courseId:s.id,sourceVideos:t,replaceExistingBunnyVideos:!1}),await h.invalidateQueries({queryKey:O.coursePreviewVideos(s.id)}),{ok:!0}):{ok:!1,reason:"Fewer than 3 Bunny lesson videos in this course"}}catch(t){return{ok:!1,reason:t instanceof Error?t.message:"Generation failed"}}finally{K(t=>{const r=new Set(t);return r.delete(s.id),r})}},Ce=async s=>{const t=await te(s);await g(),t.ok?f({title:"Preview videos generated",description:s.title}):f({title:"Generation failed",description:`${s.title}: ${t.reason}`,variant:"destructive"})},Se=(s,t)=>{b(r=>{const a=new Set(r);return t?a.add(s):a.delete(s),a})},ke=(s,t)=>{b(r=>{const a=new Set(r);return t.forEach(i=>s?a.add(i.id):a.delete(i.id)),a})},Ee=async s=>{if(s.length){F(!0);try{const t=await rs(s,os,i=>te(i));await g();const r=t.filter(i=>i.status==="fulfilled"&&i.value.ok).length,a=t.length-r;f({title:`Generated previews for ${r}/${t.length} course${t.length===1?"":"s"}`,description:a?`${a} course${a===1?"":"s"} could not be generated (fewer than 3 Bunny videos or an error).`:void 0,variant:a?"destructive":void 0}),b(new Set)}finally{F(!1)}}},C=n.useMemo(()=>o?c.filter(s=>s.id===o):c,[c,o]),A=n.useMemo(()=>({total:C.length,withPreviews:C.filter(s=>!!x[s.id]).length}),[C,x]),S=n.useMemo(()=>{const s=I.trim().toLowerCase();return C.filter(t=>{const r=!!x[t.id];return E==="has_preview"&&!r||E==="no_preview"&&r?!1:s?`${t.title} ${t.slug} ${t.id}`.toLowerCase().includes(s):!0})},[C,x,I,E]);return e.jsxs("div",{className:"space-y-4 p-4 sm:p-6",children:[e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"flex items-center gap-2 text-xl font-semibold",children:[e.jsx(_e,{className:"h-5 w-5 text-primary"}),"Preview Videos"]}),e.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Manage the public preview for every course, newest first. Generate three short Bunny previews from course lesson videos."})]}),e.jsxs(p,{variant:"outline",size:"sm",onClick:()=>{$(),g()},disabled:N,children:[N?e.jsx(j,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(Me,{className:"mr-2 h-4 w-4"}),"Refresh"]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsxs(k,{variant:"outline",children:[A.total," courses"]}),e.jsxs(k,{variant:"secondary",children:[A.withPreviews," with previews"]}),e.jsxs(k,{variant:"outline",children:[A.total-A.withPreviews," not generated"]})]}),e.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(Ke,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),e.jsx(Fe,{className:"pl-9",placeholder:"Search by course title, slug, or id...",value:I,onChange:s=>he(s.target.value)})]}),e.jsx("div",{className:"flex flex-wrap gap-1",children:[["all","All"],["has_preview","Has previews"],["no_preview","No previews"]].map(([s,t])=>e.jsx(p,{size:"sm",variant:E===s?"default":"outline",onClick:()=>xe(s),children:t},s))})]}),N?e.jsxs("div",{className:"flex items-center justify-center gap-2 rounded-lg border bg-card p-10 text-sm text-muted-foreground",children:[e.jsx(j,{className:"h-5 w-5 animate-spin"}),"Loading preview video overview..."]}):e.jsxs("div",{className:"space-y-2",children:[S.length>0?e.jsxs("div",{className:"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/30 px-3 py-2 text-sm",children:[e.jsx(T,{checked:S.every(s=>v.has(s.id)),onCheckedChange:s=>ke(s===!0,S)}),e.jsx("span",{className:"text-muted-foreground",children:v.size?`${v.size} selected`:"Select all visible"}),v.size>0?e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[e.jsx(p,{size:"sm",variant:"ghost",onClick:()=>b(new Set),disabled:B,children:"Clear"}),e.jsxs(p,{size:"sm",disabled:B,onClick:()=>void Ee(c.filter(s=>v.has(s.id))),children:[B?e.jsx(j,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(ie,{className:"mr-2 h-4 w-4"}),"Generate previews for selected"]})]}):null]}):null,S.map(s=>{const t=x[s.id],r=P===s.id,a=fe.has(s.id),i=pe[s.id],l=ds(t,i),w=!t&&i!==void 0&&i<3;return e.jsxs("div",{id:`preview-course-${s.id}`,className:"rounded-lg border bg-card p-3 shadow-sm",children:[e.jsxs("div",{className:"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between",children:[e.jsxs("div",{className:"flex min-w-0 flex-1 items-start gap-3",children:[e.jsx(T,{className:"mt-1",checked:v.has(s.id),onCheckedChange:u=>Se(s.id,u===!0)}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"break-words font-medium",children:s.title}),e.jsxs(k,{variant:"outline",className:Qe("gap-1",l.className),children:[l.icon==="check"?e.jsx(ns,{className:"h-3.5 w-3.5"}):l.icon==="sparkles"?e.jsx(He,{className:"h-3.5 w-3.5"}):e.jsx(is,{className:"h-3.5 w-3.5"}),l.label]})]}),e.jsxs("p",{className:"mt-0.5 break-all text-xs text-muted-foreground",children:[s.id,s.slug?` • ${s.slug}`:""," • Created ",Je(s.createdAt),t!=null&&t.updatedAt?` • Updated ${We(t.updatedAt)}`:""]})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(p,{size:"sm",variant:"outline",disabled:a||B||w,title:w?"This course has fewer than 3 Bunny lesson videos":void 0,onClick:()=>void Ce(s),children:[a?e.jsx(j,{className:"mr-1 h-4 w-4 animate-spin"}):e.jsx(ie,{className:"mr-1 h-4 w-4"}),"Generate previews"]}),s.slug?e.jsx(p,{size:"sm",variant:"ghost",asChild:!0,children:e.jsxs(Ye,{to:`/courses/${s.slug}`,target:"_blank",children:[e.jsx(Xe,{className:"mr-1 h-4 w-4"}),"Course page"]})}):null,e.jsxs(p,{size:"sm",variant:"outline",onClick:()=>je(s.id),children:[r?e.jsx(Ze,{className:"mr-1 h-4 w-4"}):e.jsx(es,{className:"mr-1 h-4 w-4"}),"Manage"]})]})]}),r?e.jsxs("div",{className:"mt-3 space-y-5 border-t pt-3",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"mb-2 text-sm font-medium",children:"Current previews"}),t!=null&&t.videos.length?e.jsx("div",{className:"grid gap-3 md:grid-cols-3",children:t.videos.map(u=>e.jsxs("div",{className:"overflow-hidden rounded-lg border",children:[e.jsx("div",{className:"aspect-video bg-black",children:e.jsx("iframe",{src:cs(u.embedUrl),title:u.title,className:"h-full w-full",allow:"encrypted-media; picture-in-picture"})}),e.jsx("div",{className:"p-2 text-xs font-medium",children:u.title})]},u.id))}):e.jsx("div",{className:"rounded-lg border border-dashed p-6 text-center text-sm text-muted-foreground",children:"No published previews found for this course."})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center justify-between",children:[e.jsx("h3",{className:"text-sm font-medium",children:"Choose three source videos"}),e.jsxs(k,{variant:"secondary",children:[R.length," Bunny videos"]})]}),ge?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(j,{className:"h-4 w-4 animate-spin"}),"Loading lesson videos..."]}):R.length?e.jsx("div",{className:"grid max-h-72 gap-2 overflow-y-auto md:grid-cols-2",children:R.map(u=>{const V=we.has(u.embedUrl);return e.jsxs("button",{type:"button",disabled:L,onClick:()=>be(u),className:`flex items-center gap-3 rounded-lg border p-2.5 text-left text-sm transition-colors ${V?"border-primary bg-primary/5":"hover:bg-muted"}`,children:[e.jsx("span",{className:`flex h-7 w-7 shrink-0 items-center justify-center rounded-full ${V?"bg-primary text-primary-foreground":"bg-muted"}`,children:V?e.jsx(ss,{className:"h-3.5 w-3.5"}):e.jsx(ls,{className:"h-3.5 w-3.5"})}),e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block truncate font-medium",children:u.title}),e.jsx("span",{className:"block truncate text-xs text-muted-foreground",children:u.embedUrl})]})]},u.id)})}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"No Bunny lesson videos were found in this course."})]}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-t pt-3",children:[e.jsxs("p",{className:"text-sm text-muted-foreground",children:[ee.size,"/3 unique sources selected"]}),e.jsx(p,{size:"sm",onClick:()=>G(!0),disabled:!se||L,children:L?e.jsxs(e.Fragment,{children:[e.jsx(j,{className:"mr-2 h-4 w-4 animate-spin"}),"Generating previews..."]}):t?"Regenerate previews":"Generate previews"})]}),L&&e.jsx("div",{className:"rounded-md border border-blue-200 bg-blue-50 p-3 text-sm text-blue-900",children:"Generation can take several minutes. Keep this page open until the request finishes."})]}):null]},s.id)}),S.length?null:e.jsx("div",{className:"rounded-lg border bg-card p-8 text-center text-sm text-muted-foreground",children:"No courses match the current search or filter."})]}),e.jsx(Pe,{open:ve,onOpenChange:G,children:e.jsxs(Be,{children:[e.jsxs(Le,{children:[e.jsx(Ae,{children:m&&x[m.id]?"Regenerate course previews?":"Generate course previews?"}),e.jsx(Ie,{children:"The pipeline will create three Bunny videos and publish their metadata for this course."})]}),m&&x[m.id]&&e.jsxs("div",{className:"space-y-3 rounded-md border p-3",children:[e.jsxs("label",{className:"flex items-start gap-3 text-sm",children:[e.jsx(T,{checked:U,onCheckedChange:s=>X(s===!0)}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:"Replace existing Bunny preview videos"}),e.jsx("span",{className:"block text-muted-foreground",children:"Leave disabled to preserve existing Bunny assets. Enabling this may permanently remove them."})]})]}),U&&e.jsxs("div",{className:"flex gap-2 text-sm text-destructive",children:[e.jsx(ts,{className:"h-4 w-4 shrink-0"}),"Existing Bunny preview assets may be deleted."]})]}),e.jsxs(Re,{children:[e.jsx(Ge,{children:"Cancel"}),e.jsx(Ue,{onClick:ye,children:m&&x[m.id]?"Regenerate":"Generate"})]})]})})]})}export{ys as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.