openlearn-next 0.2.2 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/assets/AdminDirectoryView-Cai0cQqi.js +1 -0
  2. package/dist/assets/BatchPickerModal-CKQyeY6R.js +1 -0
  3. package/dist/assets/ClassesView-Cxgfcrx1.js +19 -0
  4. package/dist/assets/CloudDriveModal-DgDurUBT.js +1 -0
  5. package/dist/assets/ComputerLabView-CUCO2VIV.js +1 -0
  6. package/dist/assets/CourseManagement-DSCOjuIC.js +1 -0
  7. package/dist/assets/CourseWizardModal-B3QnFxvj.js +3 -0
  8. package/dist/assets/CoursewareHubPanel-CAaf22Qm.js +1 -0
  9. package/dist/assets/Dashboard-BnF7YAQi.js +8 -0
  10. package/dist/assets/ExportWeightModal-BlS2auLs.js +1 -0
  11. package/dist/assets/HelpTour-ZgEkRnin.js +1 -0
  12. package/dist/assets/HelpView-BP581QYZ.js +204 -0
  13. package/dist/assets/ImportLessonsModal-BZZRDBRU.js +1 -0
  14. package/dist/assets/ImportModal-mkWuDoAN.js +1 -0
  15. package/dist/assets/InteractiveCoursewareViewer-EIRNulEo.js +1 -0
  16. package/dist/assets/InteractiveWhiteboard-D360IHbP.js +102 -0
  17. package/dist/assets/LazyCourseware-qE4CY67E.js +1 -0
  18. package/dist/assets/LazyWhiteboard-B5JmqHZ5.js +2 -0
  19. package/dist/assets/LessonEditorView-C0czhtmf.js +1 -0
  20. package/dist/assets/LiveClassroomView-CrTY3jhP.js +1 -0
  21. package/dist/assets/NotificationDetailModal-dndFrE7p.js +1 -0
  22. package/dist/assets/PluginView-QS2b6nSF.js +65 -0
  23. package/dist/assets/ProcessLogsModal-8mVp07ic.js +1 -0
  24. package/dist/assets/QuizGeneratorModal-DpTFYbVJ.js +1 -0
  25. package/dist/assets/StudentAssignmentView-YxVJ5wkl.js +1 -0
  26. package/dist/assets/StudentLessonView-D1gYdLM1.js +1 -0
  27. package/dist/assets/StudentPreviewModal-CG8bgUeI.js +1 -0
  28. package/dist/assets/StudentView-CmSL3cDw.js +1 -0
  29. package/dist/assets/SystemResourceLibraryModal-Dnh7F5Vm.js +1 -0
  30. package/dist/assets/TeacherView-BqXb0izg.js +2 -0
  31. package/dist/assets/TimetableView-zce3okQn.js +6 -0
  32. package/dist/assets/index-BrEBeWAQ.js +14 -0
  33. package/dist/assets/index-BxA9vp--.js +129 -0
  34. package/dist/assets/index-CATki2cp.css +1 -0
  35. package/dist/assets/index-Cq_aKTfc.js +1 -0
  36. package/dist/assets/{index.es-D071ILbD.js → index.es-DZ6UeYE-.js} +2 -2
  37. package/dist/assets/vendor-charts-B7ViBL9w.js +71 -0
  38. package/dist/assets/vendor-icons-BvCtGbt1.js +8221 -0
  39. package/dist/assets/vendor-konva-CzxOmTv9.js +49 -0
  40. package/dist/assets/vendor-motion-Dz5URUo4.js +9 -0
  41. package/dist/assets/vendor-pdf-CVyNPGVr.js +191 -0
  42. package/dist/assets/{vendor-pptx-CJ3I-KT0.js → vendor-pptx-B0hlo0eh.js} +1 -1
  43. package/dist/assets/vendor-react-0Lg0vA-4.js +49 -0
  44. package/dist/assets/vendor-utils-4FcTwKPj.js +1 -0
  45. package/dist/index.html +2 -3
  46. package/dist/server.cjs +164 -46
  47. package/package.json +1 -1
  48. package/dist/assets/courseware-CL7gjXZj.js +0 -1
  49. package/dist/assets/index-4xDvXGZ_.js +0 -682
  50. package/dist/assets/index-CaJDJGky.css +0 -1
  51. package/dist/assets/vendor-html2canvas-B0tyYwQk.js +0 -22
  52. package/dist/assets/vendor-konva-GivUq6dt.js +0 -89
  53. package/dist/assets/whiteboard-Dp8tFXTO.js +0 -8343
  54. /package/dist/assets/{purify.es-V6uLfjnH.js → vendor-content-V6uLfjnH.js} +0 -0
@@ -0,0 +1 @@
1
+ import{R as O,g as A,c as re}from"./vendor-react-0Lg0vA-4.js";const ee=n=>{let r;const t=new Set,s=(u,e)=>{const o=typeof u=="function"?u(r):u;if(!Object.is(o,r)){const l=r;r=e??(typeof o!="object"||o===null)?o:Object.assign({},r,o),t.forEach(g=>g(r,l))}},i=()=>r,c={setState:s,getState:i,getInitialState:()=>y,subscribe:u=>(t.add(u),()=>t.delete(u))},y=r=n(s,i,c);return c},Xt=(n=>n?ee(n):ee),Jt=n=>n;function Qt(n,r=Jt){const t=O.useSyncExternalStore(n.subscribe,O.useCallback(()=>r(n.getState()),[n,r]),O.useCallback(()=>r(n.getInitialState()),[n,r]));return O.useDebugValue(t),t}const Yt=n=>{const r=Xt(n),t=s=>Qt(r,s);return Object.assign(t,r),t},li=(n=>Yt);function St(n){var r,t,s="";if(typeof n=="string"||typeof n=="number")s+=n;else if(typeof n=="object")if(Array.isArray(n)){var i=n.length;for(r=0;r<i;r++)n[r]&&(t=St(n[r]))&&(s&&(s+=" "),s+=t)}else for(t in n)n[t]&&(s&&(s+=" "),s+=t);return s}function gi(){for(var n,r,t=0,s="",i=arguments.length;t<i;t++)(n=arguments[t])&&(r=St(n))&&(s&&(s+=" "),s+=r);return s}var w={},x={},te;function vt(){if(te)return x;te=1;function n(r){return r==="__proto__"}return x.isUnsafeProperty=n,x}var j={},ne;function _(){if(ne)return j;ne=1;function n(r){switch(typeof r){case"number":case"symbol":return!1;case"string":return r.includes(".")||r.includes("[")||r.includes("]")}}return j.isDeepKey=n,j}var T={},ie;function S(){if(ie)return T;ie=1;function n(r){return typeof r=="string"||typeof r=="symbol"?r:Object.is(r?.valueOf?.(),-0)?"-0":String(r)}return T.toKey=n,T}var M={},L={},se;function Ct(){if(se)return L;se=1;function n(r){if(r==null)return"";if(typeof r=="string")return r;if(Array.isArray(r))return r.map(n).join(",");const t=String(r);return t==="0"&&Object.is(Number(r),-0)?"-0":t}return L.toString=n,L}var ue;function v(){if(ue)return M;ue=1;const n=S(),r=Ct();function t(s){if(Array.isArray(s))return s.map(n.toKey);if(typeof s=="symbol")return[s];s=r.toString(s);const i=[],a=s.length;if(a===0)return i;let f=0,c="",y="",u=!1;for(s.charCodeAt(0)===46&&(i.push(""),f++);f<a;){const e=s[f];y?e==="\\"&&f+1<a?(f++,c+=s[f]):e===y?y="":c+=e:u?e==='"'||e==="'"?y=e:e==="]"?(u=!1,i.push(c),c=""):c+=e:e==="["?(u=!0,c&&(i.push(c),c="")):e==="."?c&&(i.push(c),c=""):c+=e,f++}return c&&i.push(c),i}return M.toPath=t,M}var ae;function P(){if(ae)return w;ae=1;const n=vt(),r=_(),t=S(),s=v();function i(f,c,y){if(f==null)return y;switch(typeof c){case"string":{if(n.isUnsafeProperty(c))return y;const u=f[c];return u===void 0?r.isDeepKey(c)?i(f,s.toPath(c),y):y:u}case"number":case"symbol":{typeof c=="number"&&(c=t.toKey(c));const u=f[c];return u===void 0?y:u}default:{if(Array.isArray(c))return a(f,c,y);if(Object.is(c?.valueOf(),-0)?c="-0":c=String(c),n.isUnsafeProperty(c))return y;const u=f[c];return u===void 0?y:u}}}function a(f,c,y){if(c.length===0)return y;let u=f;for(let e=0;e<c.length;e++){if(u==null||n.isUnsafeProperty(c[e]))return y;u=u[c[e]]}return u===void 0?y:u}return w.get=i,w}var E,oe;function rn(){return oe||(oe=1,E=P().get),E}var en=rn();const qi=A(en);var W={},K={},fe;function tn(){if(fe)return K;fe=1;function n(r,t){const s=new Map;for(let i=0;i<r.length;i++){const a=r[i],f=t(a,i,r);s.has(f)||s.set(f,a)}return Array.from(s.values())}return K.uniqBy=n,K}var N={},ce;function nn(){if(ce)return N;ce=1;function n(r,t){return function(...s){return r.apply(this,s.slice(0,t))}}return N.ary=n,N}var U={},ye;function R(){if(ye)return U;ye=1;function n(r){return r}return U.identity=n,U}var k={},F={},le;function sn(){if(le)return F;le=1;const n=P();function r(t){return function(s){return n.get(s,t)}}return F.property=r,F}var G={},Z={},$={},V={},ge;function Pt(){if(ge)return V;ge=1;function n(r){return r==null||typeof r!="object"&&typeof r!="function"}return V.isPrimitive=n,V}var z={},qe;function Rt(){if(qe)return z;qe=1;function n(r){return ArrayBuffer.isView(r)&&!(r instanceof DataView)}return z.isTypedArray=n,z}var H={},he;function Dt(){if(he)return H;he=1;function n(r){return Object.getOwnPropertySymbols(r).filter(t=>Object.prototype.propertyIsEnumerable.call(r,t))}return H.getSymbols=n,H}var X={},me;function Cr(){if(me)return X;me=1;function n(r){return r==null?r===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(r)}return X.getTag=n,X}var p={},de;function wt(){if(de)return p;de=1;const n="[object RegExp]",r="[object String]",t="[object Number]",s="[object Boolean]",i="[object Arguments]",a="[object Symbol]",f="[object Date]",c="[object Map]",y="[object Set]",u="[object Array]",e="[object Function]",o="[object ArrayBuffer]",l="[object Object]",g="[object Error]",h="[object DataView]",m="[object Uint8Array]",q="[object Uint8ClampedArray]",d="[object Uint16Array]",b="[object Uint32Array]",I="[object BigUint64Array]",Ft="[object Int8Array]",Gt="[object Int16Array]",Zt="[object Int32Array]",Vt="[object BigInt64Array]",zt="[object Float32Array]",Ht="[object Float64Array]";return p.argumentsTag=i,p.arrayBufferTag=o,p.arrayTag=u,p.bigInt64ArrayTag=Vt,p.bigUint64ArrayTag=I,p.booleanTag=s,p.dataViewTag=h,p.dateTag=f,p.errorTag=g,p.float32ArrayTag=zt,p.float64ArrayTag=Ht,p.functionTag=e,p.int16ArrayTag=Gt,p.int32ArrayTag=Zt,p.int8ArrayTag=Ft,p.mapTag=c,p.numberTag=t,p.objectTag=l,p.regexpTag=n,p.setTag=y,p.stringTag=r,p.symbolTag=a,p.uint16ArrayTag=d,p.uint32ArrayTag=b,p.uint8ArrayTag=m,p.uint8ClampedArrayTag=q,p}var J={},Q={},pe;function un(){if(pe)return Q;pe=1;const n=typeof globalThis=="object"&&globalThis||typeof window=="object"&&window||typeof self=="object"&&self||typeof re=="object"&&re||(function(){return this})()||Function("return this")();return Q.globalThis_=n,Q}var be;function xt(){if(be)return J;be=1;const n=un();function r(t){return typeof n.globalThis_.Buffer<"u"&&n.globalThis_.Buffer.isBuffer(t)}return J.isBuffer=r,J}var Ae;function jt(){if(Ae)return $;Ae=1;const n=Pt(),r=Rt(),t=Dt(),s=Cr(),i=wt(),a=xt();function f(e,o){return c(e,void 0,e,new Map,o)}function c(e,o,l,g=new Map,h=void 0){const m=h?.(e,o,l,g);if(m!==void 0)return m;if(n.isPrimitive(e))return e;if(g.has(e))return g.get(e);if(Array.isArray(e)){const q=new Array(e.length);g.set(e,q);for(let d=0;d<e.length;d++)q[d]=c(e[d],d,l,g,h);return Object.hasOwn(e,"index")&&(q.index=e.index),Object.hasOwn(e,"input")&&(q.input=e.input),q}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp){const q=new RegExp(e.source,e.flags);return q.lastIndex=e.lastIndex,q}if(e instanceof Map){const q=new Map;g.set(e,q);for(const[d,b]of e)q.set(d,c(b,d,l,g,h));return q}if(e instanceof Set){const q=new Set;g.set(e,q);for(const d of e)q.add(c(d,void 0,l,g,h));return q}if(a.isBuffer(e))return e.subarray();if(r.isTypedArray(e)){const q=new(Object.getPrototypeOf(e)).constructor(e.length);g.set(e,q);for(let d=0;d<e.length;d++)q[d]=c(e[d],d,l,g,h);return q}if(e instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&e instanceof SharedArrayBuffer)return e.slice(0);if(e instanceof DataView){const q=new DataView(e.buffer.slice(0),e.byteOffset,e.byteLength);return g.set(e,q),y(q,e,l,g,h),q}if(typeof File<"u"&&e instanceof File){const q=new File([e],e.name,{type:e.type});return g.set(e,q),y(q,e,l,g,h),q}if(typeof Blob<"u"&&e instanceof Blob){const q=new Blob([e],{type:e.type});return g.set(e,q),y(q,e,l,g,h),q}if(e instanceof Error){const q=structuredClone(e);return g.set(e,q),q.message=e.message,q.name=e.name,q.stack=e.stack,q.cause=e.cause,q.constructor=e.constructor,y(q,e,l,g,h),q}if(e instanceof Boolean){const q=new Boolean(e.valueOf());return g.set(e,q),y(q,e,l,g,h),q}if(e instanceof Number){const q=new Number(e.valueOf());return g.set(e,q),y(q,e,l,g,h),q}if(e instanceof String){const q=new String(e.valueOf());return g.set(e,q),y(q,e,l,g,h),q}if(typeof e=="object"&&u(e)){const q=Object.create(Object.getPrototypeOf(e));return g.set(e,q),y(q,e,l,g,h),q}return e}function y(e,o,l=e,g,h){const m=[...Object.keys(o),...t.getSymbols(o)];for(let q=0;q<m.length;q++){const d=m[q],b=Object.getOwnPropertyDescriptor(e,d);(b==null||b.writable)&&(e[d]=c(o[d],d,l,g,h))}}function u(e){switch(s.getTag(e)){case i.argumentsTag:case i.arrayTag:case i.arrayBufferTag:case i.dataViewTag:case i.booleanTag:case i.dateTag:case i.float32ArrayTag:case i.float64ArrayTag:case i.int8ArrayTag:case i.int16ArrayTag:case i.int32ArrayTag:case i.mapTag:case i.numberTag:case i.objectTag:case i.regexpTag:case i.setTag:case i.stringTag:case i.symbolTag:case i.uint8ArrayTag:case i.uint8ClampedArrayTag:case i.uint16ArrayTag:case i.uint32ArrayTag:return!0;default:return!1}}return $.cloneDeepWith=f,$.cloneDeepWithImpl=c,$.copyProperties=y,$}var Ie;function an(){if(Ie)return Z;Ie=1;const n=jt();function r(t){return n.cloneDeepWithImpl(t,void 0,t,new Map,void 0)}return Z.cloneDeep=r,Z}var Y={},C={},rr={},$e;function Tt(){if($e)return rr;$e=1;function n(r,t){return r===t||Number.isNaN(r)&&Number.isNaN(t)}return rr.isEqualsSameValueZero=n,rr}var er={},Be;function Mt(){if(Be)return er;Be=1;function n(r){return r!==null&&(typeof r=="object"||typeof r=="function")}return er.isObject=n,er}var Oe;function on(){if(Oe)return C;Oe=1;const n=Pt(),r=Tt(),t=Mt();function s(u,e,o){return typeof o!="function"?s(u,e,()=>{}):i(u,e,function l(g,h,m,q,d,b){const I=o(g,h,m,q,d,b);return I!==void 0?!!I:i(g,h,l,b)},new Map)}function i(u,e,o,l){if(e===u)return!0;switch(typeof e){case"object":return a(u,e,o,l);case"function":return Object.keys(e).length>0?i(u,{...e},o,l):r.isEqualsSameValueZero(u,e);default:return t.isObject(u)?typeof e=="string"?e==="":!0:r.isEqualsSameValueZero(u,e)}}function a(u,e,o,l){if(e==null)return!0;if(Array.isArray(e))return c(u,e,o,l);if(e instanceof Map)return f(u,e,o,l);if(e instanceof Set)return y(u,e,o,l);const g=Object.keys(e);if(u==null||n.isPrimitive(u))return g.length===0;if(g.length===0)return!0;if(l?.has(e))return l.get(e)===u;l?.set(e,u);try{for(let h=0;h<g.length;h++){const m=g[h];if(!n.isPrimitive(u)&&!(m in u)||e[m]===void 0&&u[m]!==void 0||e[m]===null&&u[m]!==null||!o(u[m],e[m],m,u,e,l))return!1}return!0}finally{l?.delete(e)}}function f(u,e,o,l){if(e.size===0)return!0;if(!(u instanceof Map))return!1;for(const[g,h]of e.entries())if(o(u.get(g),h,g,u,e,l)===!1)return!1;return!0}function c(u,e,o,l){if(e.length===0)return!0;if(!Array.isArray(u))return!1;const g=new Set;for(let h=0;h<e.length;h++){const m=e[h];let q=!1;for(let d=0;d<u.length;d++){if(g.has(d))continue;const b=u[d];let I=!1;if(o(b,m,h,u,e,l)&&(I=!0),I){g.add(d),q=!0;break}}if(!q)return!1}return!0}function y(u,e,o,l){return e.size===0?!0:u instanceof Set?c([...u],[...e],o,l):!1}return C.isMatchWith=s,C}var _e;function Lt(){if(_e)return Y;_e=1;const n=on();function r(t,s){return n.isMatchWith(t,s,()=>{})}return Y.isMatch=r,Y}var Se;function fn(){if(Se)return G;Se=1;const n=an(),r=Lt();function t(s){return s=n.cloneDeep(s),i=>r.isMatch(i,s)}return G.matches=t,G}var tr={},nr={},ir={},ve;function Et(){if(ve)return ir;ve=1;const n=Cr(),r=wt(),t=jt();function s(i,a){return t.cloneDeepWith(i,(f,c,y,u)=>{const e=a?.(f,c,y,u);if(e!==void 0)return e;if(typeof i=="object"){if(n.getTag(i)==="[object Object]"&&typeof i.constructor!="function"){const o={};return u.set(i,o),t.copyProperties(o,i,y,u),o}switch(Object.prototype.toString.call(i)){case r.numberTag:case r.stringTag:case r.booleanTag:{const o=new i.constructor(i?.valueOf());return t.copyProperties(o,i),o}case r.argumentsTag:{const o={};return t.copyProperties(o,i),o.length=i.length,o[Symbol.iterator]=i[Symbol.iterator],o}default:return}}})}return ir.cloneDeepWith=s,ir}var Pe;function cn(){if(Pe)return nr;Pe=1;const n=Et();function r(t){return n.cloneDeepWith(t)}return nr.cloneDeep=r,nr}var sr={},ur={},Re;function Wt(){if(Re)return ur;Re=1;const n=/^(?:0|[1-9]\d*)$/;function r(t,s=Number.MAX_SAFE_INTEGER){switch(typeof t){case"number":return Number.isInteger(t)&&t>=0&&t<s;case"symbol":return!1;case"string":return n.test(t)}}return ur.isIndex=r,ur}var ar={},De;function yn(){if(De)return ar;De=1;const n=Cr();function r(t){return t!==null&&typeof t=="object"&&n.getTag(t)==="[object Arguments]"}return ar.isArguments=r,ar}var we;function ln(){if(we)return sr;we=1;const n=_(),r=v(),t=Wt(),s=yn();function i(a,f){let c;if(Array.isArray(f)?c=f:typeof f=="string"&&n.isDeepKey(f)&&a?.[f]==null?c=r.toPath(f):c=[f],c.length===0)return!1;let y=a;for(let u=0;u<c.length;u++){const e=c[u];if((y==null||!Object.hasOwn(y,e))&&!((Array.isArray(y)||s.isArguments(y))&&t.isIndex(e)&&e<y.length))return!1;y=y[e]}return!0}return sr.has=i,sr}var xe;function gn(){if(xe)return tr;xe=1;const n=S(),r=P(),t=Lt(),s=cn(),i=ln();function a(f,c){switch(typeof f){case"object":Object.is(f?.valueOf(),-0)&&(f="-0");break;case"number":f=n.toKey(f);break}return c=s.cloneDeep(c),function(y){const u=r.get(y,f);return u===void 0?i.has(y,f):c===void 0?u===void 0:t.isMatch(u,c)}}return tr.matchesProperty=a,tr}var je;function D(){if(je)return k;je=1;const n=R(),r=sn(),t=fn(),s=gn();function i(a){if(a==null)return n.identity;switch(typeof a){case"function":return a;case"object":return Array.isArray(a)&&a.length===2?s.matchesProperty(a[0],a[1]):t.matches(a);case"string":case"symbol":case"number":return r.property(a)}}return k.iteratee=i,k}var or={},fr={},cr={},Te;function qn(){if(Te)return cr;Te=1;function n(r){return Number.isSafeInteger(r)&&r>=0}return cr.isLength=n,cr}var Me;function B(){if(Me)return fr;Me=1;const n=qn();function r(t){return t!=null&&typeof t!="function"&&n.isLength(t.length)}return fr.isArrayLike=r,fr}var yr={},Le;function hn(){if(Le)return yr;Le=1;function n(r){return typeof r=="object"&&r!==null}return yr.isObjectLike=n,yr}var Ee;function mn(){if(Ee)return or;Ee=1;const n=B(),r=hn();function t(s){return r.isObjectLike(s)&&n.isArrayLike(s)}return or.isArrayLikeObject=t,or}var We;function dn(){if(We)return W;We=1;const n=tn(),r=nn(),t=R(),s=D(),i=mn();function a(f,c=t.identity){return i.isArrayLikeObject(f)?n.uniqBy(Array.from(f),r.ary(s.iteratee(c),1)):[]}return W.uniqBy=a,W}var lr,Ke;function pn(){return Ke||(Ke=1,lr=dn().uniqBy),lr}var bn=pn();const hi=A(bn);var gr={},qr={},Ne;function An(){if(Ne)return qr;Ne=1;function n(r,t=1){const s=[],i=Math.floor(t),a=(f,c)=>{for(let y=0;y<f.length;y++){const u=f[y];Array.isArray(u)&&c<i?a(u,c+1):s.push(u)}};return a(r,0),s}return qr.flatten=n,qr}var hr={},Ue;function Kt(){if(Ue)return hr;Ue=1;const n=Tt(),r=B(),t=Mt(),s=Wt();function i(a,f,c){return t.isObject(c)&&(typeof f=="number"&&r.isArrayLike(c)&&s.isIndex(f)&&f<c.length||typeof f=="string"&&f in c)?n.isEqualsSameValueZero(c[f],a):!1}return hr.isIterateeCall=i,hr}var mr={},dr={},ke;function In(){if(ke)return dr;ke=1;function n(t){return typeof t=="symbol"?1:t===null?2:t===void 0?3:t!==t?4:0}const r=(t,s,i)=>{if(t!==s){const a=n(t),f=n(s);if(a===f&&a===0){if(t<s)return i==="desc"?1:-1;if(t>s)return i==="desc"?-1:1}return i==="desc"?f-a:a-f}return 0};return dr.compareValues=r,dr}var pr={},br={},Fe;function Nt(){if(Fe)return br;Fe=1;function n(r){return typeof r=="symbol"||r instanceof Symbol}return br.isSymbol=n,br}var Ge;function $n(){if(Ge)return pr;Ge=1;const n=Nt(),r=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,t=/^\w*$/;function s(i,a){return Array.isArray(i)?!1:typeof i=="number"||typeof i=="boolean"||i==null||n.isSymbol(i)?!0:typeof i=="string"&&(t.test(i)||!r.test(i))||a!=null&&Object.hasOwn(a,i)}return pr.isKey=s,pr}var Ze;function Bn(){if(Ze)return mr;Ze=1;const n=v(),r=In(),t=$n();function s(i,a,f,c){if(i==null)return[];f=c?void 0:f,Array.isArray(i)||(i=Object.values(i)),Array.isArray(a)||(a=a==null?[null]:[a]),a.length===0&&(a=[null]),Array.isArray(f)||(f=f==null?[]:[f]),f=f.map(o=>String(o));const y=(o,l)=>{let g=o;for(let h=0;h<l.length&&g!=null;++h)g=g[l[h]];return g},u=(o,l)=>l==null||o==null?l:typeof o=="object"&&"key"in o?Object.hasOwn(l,o.key)?l[o.key]:y(l,o.path):typeof o=="function"?o(l):Array.isArray(o)?y(l,o):typeof l=="object"?l[o]:l,e=a.map(o=>(Array.isArray(o)&&o.length===1&&(o=o[0]),o==null||typeof o=="function"||Array.isArray(o)||t.isKey(o)?o:{key:o,path:n.toPath(o)}));return i.map(o=>({original:o,criteria:e.map(l=>u(l,o))})).slice().sort((o,l)=>{for(let g=0;g<e.length;g++){const h=r.compareValues(o.criteria[g],l.criteria[g],f[g]);if(h!==0)return h}return 0}).map(o=>o.original)}return mr.orderBy=s,mr}var Ve;function On(){if(Ve)return gr;Ve=1;const n=An(),r=Kt(),t=Bn();function s(i,...a){const f=a.length;return f>1&&r.isIterateeCall(i,a[0],a[1])?a=[]:f>2&&r.isIterateeCall(a[0],a[1],a[2])&&(a=[a[0]]),t.orderBy(i,n.flatten(a),["asc"])}return gr.sortBy=s,gr}var Ar,ze;function _n(){return ze||(ze=1,Ar=On().sortBy),Ar}var Sn=_n();const mi=A(Sn);var Ir={},$r={},Br={},He;function vn(){if(He)return Br;He=1;function n(r,t,{signal:s,edges:i}={}){let a,f=null;const c=i!=null&&i.includes("leading"),y=i==null||i.includes("trailing"),u=()=>{f!==null&&(r.apply(a,f),a=void 0,f=null)},e=()=>{y&&u(),h()};let o=null;const l=()=>{o!=null&&clearTimeout(o),o=setTimeout(()=>{o=null,e()},t)},g=()=>{o!==null&&(clearTimeout(o),o=null)},h=()=>{g(),a=void 0,f=null},m=()=>{u()},q=function(...d){if(s?.aborted)return;a=this,f=d;const b=o==null;l(),c&&b&&u()};return q.schedule=l,q.cancel=h,q.flush=m,s?.addEventListener("abort",h,{once:!0}),q}return Br.debounce=n,Br}var Xe;function Pn(){if(Xe)return $r;Xe=1;const n=vn();function r(t,s=0,i={}){typeof i!="object"&&(i={});const{leading:a=!1,trailing:f=!0,maxWait:c}=i,y=Array(2);a&&(y[0]="leading"),f&&(y[1]="trailing");let u,e=null;const o=n.debounce(function(...h){u=t.apply(this,h),e=null},s,{edges:y}),l=function(...h){return c!=null&&(e===null&&(e=Date.now()),Date.now()-e>=c)?(u=t.apply(this,h),e=Date.now(),o.cancel(),o.schedule(),u):(o.apply(this,h),u)},g=()=>(o.flush(),u);return l.cancel=o.cancel,l.flush=g,l}return $r.debounce=r,$r}var Je;function Rn(){if(Je)return Ir;Je=1;const n=Pn();function r(t,s=0,i={}){const{leading:a=!0,trailing:f=!0}=i;return n.debounce(t,s,{leading:a,maxWait:s,trailing:f})}return Ir.throttle=r,Ir}var Or,Qe;function Dn(){return Qe||(Qe=1,Or=Rn().throttle),Or}var wn=Dn();const di=A(wn);var _r={},Sr={},vr={},Ye;function xn(){if(Ye)return vr;Ye=1;const n=Nt();function r(t){return n.isSymbol(t)?NaN:Number(t)}return vr.toNumber=r,vr}var Ce;function Ut(){if(Ce)return Sr;Ce=1;const n=xn();function r(t){return t?(t=n.toNumber(t),t===1/0||t===-1/0?(t<0?-1:1)*Number.MAX_VALUE:t===t?t:0):t===0?t:0}return Sr.toFinite=r,Sr}var rt;function jn(){if(rt)return _r;rt=1;const n=Ut(),r=Kt();function t(s,i,a){a&&typeof a!="number"&&r.isIterateeCall(s,i,a)&&(i=a=void 0),s=n.toFinite(s),i===void 0?(i=s,s=0):i=n.toFinite(i),a=a===void 0?s<i?1:-1:n.toFinite(a);const f=Math.max(Math.ceil((i-s)/(a||1)),0),c=new Array(f);for(let y=0;y<f;y++)c[y]=s,s+=a;return c}return _r.range=t,_r}var Pr,et;function Tn(){return et||(et=1,Pr=jn().range),Pr}var Mn=Tn();const pi=A(Mn);var Rr={},Dr={},tt;function Ln(){if(tt)return Dr;tt=1;function n(r,t){if(r.length===0)return;let s=r[0],i=t(s,0,r);for(let a=1;a<r.length;a++){const f=r[a],c=t(f,a,r);c>i&&(i=c,s=f)}return s}return Dr.maxBy=n,Dr}var nt;function En(){if(nt)return Rr;nt=1;const n=Ln(),r=R(),t=D();function s(i,a){if(i!=null)return n.maxBy(Array.from(i),t.iteratee(a??r.identity))}return Rr.maxBy=s,Rr}var wr,it;function Wn(){return it||(it=1,wr=En().maxBy),wr}var Kn=Wn();const bi=A(Kn);var xr={},jr={},st;function Nn(){if(st)return jr;st=1;function n(r,t){if(r.length===0)return;let s=r[0],i=t(s,0,r);for(let a=1;a<r.length;a++){const f=r[a],c=t(f,a,r);c<i&&(i=c,s=f)}return s}return jr.minBy=n,jr}var ut;function Un(){if(ut)return xr;ut=1;const n=Nn(),r=R(),t=D();function s(i,a){if(i!=null)return n.minBy(Array.from(i),t.iteratee(a??r.identity))}return xr.minBy=s,xr}var Tr,at;function kn(){return at||(at=1,Tr=Un().minBy),Tr}var Fn=kn();const Ai=A(Fn);var Mr={},ot;function kt(){if(ot)return Mr;ot=1;function n(r){if(typeof r!="object"||r==null)return!1;if(Object.getPrototypeOf(r)===null)return!0;if(Object.prototype.toString.call(r)!=="[object Object]"){const s=r[Symbol.toStringTag];return s==null||!Object.getOwnPropertyDescriptor(r,Symbol.toStringTag)?.writable?!1:r.toString()===`[object ${s}]`}let t=r;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(r)===t}return Mr.isPlainObject=n,Mr}var Lr,ft;function Gn(){return ft||(ft=1,Lr=kt().isPlainObject),Lr}var Zn=Gn();const Ii=A(Zn);var Er={},Wr={},ct;function Vn(){if(ct)return Wr;ct=1;function n(r){return r[r.length-1]}return Wr.last=n,Wr}var Kr={},yt;function zn(){if(yt)return Kr;yt=1;function n(r){return Array.isArray(r)?r:Array.from(r)}return Kr.toArray=n,Kr}var lt;function Hn(){if(lt)return Er;lt=1;const n=Vn(),r=zn(),t=B();function s(i){if(t.isArrayLike(i))return n.last(r.toArray(i))}return Er.last=s,Er}var Nr,gt;function Xn(){return gt||(gt=1,Nr=Hn().last),Nr}var Jn=Xn();const $i=A(Jn);var Ur={},kr={},qt;function Qn(){if(qt)return kr;qt=1;const n=B();function r(t,s=1){const i=[],a=Math.floor(s);if(!n.isArrayLike(t))return i;const f=(c,y)=>{for(let u=0;u<c.length;u++){const e=c[u];y<a&&(Array.isArray(e)||e?.[Symbol.isConcatSpreadable]||e!==null&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Arguments]")?Array.isArray(e)?f(e,y+1):f(Array.from(e),y+1):i.push(e)}};return f(Array.from(t),0),i}return kr.flatten=r,kr}var Fr={},ht;function Yn(){if(ht)return Fr;ht=1;const n=vt(),r=_(),t=S(),s=v(),i=P();function a(c,y){if(c==null)return!0;switch(typeof y){case"symbol":case"number":case"object":if(Array.isArray(y))return f(c,y);if(typeof y=="number"?y=t.toKey(y):typeof y=="object"&&(Object.is(y?.valueOf(),-0)?y="-0":y=String(y)),n.isUnsafeProperty(y))return!1;if(c?.[y]===void 0)return!0;try{return delete c[y],!0}catch{return!1}case"string":if(c?.[y]===void 0&&r.isDeepKey(y))return f(c,s.toPath(y));if(n.isUnsafeProperty(y))return!1;try{return delete c[y],!0}catch{return!1}}}function f(c,y){const u=y.length===1?c:i.get(c,y.slice(0,-1)),e=y[y.length-1];if(u?.[e]===void 0)return!0;if(n.isUnsafeProperty(e))return!1;try{return delete u[e],!0}catch{return!1}}return Fr.unset=a,Fr}var Gr={},Zr={},mt;function Cn(){if(mt)return Zr;mt=1;function n(r){const t=r?.constructor;return r===(typeof t=="function"?t.prototype:Object.prototype)}return Zr.isPrototype=n,Zr}var Vr={},dt;function ri(){if(dt)return Vr;dt=1;const n=Rt();function r(t){return n.isTypedArray(t)}return Vr.isTypedArray=r,Vr}var zr={},Hr={},pt;function ei(){if(pt)return Hr;pt=1;const n=Ut();function r(t){const s=n.toFinite(t),i=s%1;return i?s-i:s}return Hr.toInteger=r,Hr}var bt;function ti(){if(bt)return zr;bt=1;const n=ei();function r(t,s){if(t=n.toInteger(t),t<1||!Number.isSafeInteger(t))return[];const i=new Array(t);for(let a=0;a<t;a++)i[a]=typeof s=="function"?s(a):a;return i}return zr.times=r,zr}var At;function ni(){if(At)return Gr;At=1;const n=xt(),r=B(),t=Cn(),s=ri(),i=ti();function a(u){if(u==null)return[];switch(typeof u){case"object":case"function":return r.isArrayLike(u)?y(u):t.isPrototype(u)?c(u):f(u);default:return f(Object(u))}}function f(u){const e=[];for(const o in u)e.push(o);return e}function c(u){return f(u).filter(e=>e!=="constructor")}function y(u){const e=i.times(u.length,g=>`${g}`),o=new Set(e);n.isBuffer(u)&&(o.add("offset"),o.add("parent")),s.isTypedArray(u)&&(o.add("buffer"),o.add("byteLength"),o.add("byteOffset"));const l=f(u).filter(g=>!o.has(g));return Array.isArray(u)?[...e,...l]:[...e.filter(g=>Object.hasOwn(u,g)),...l]}return Gr.keysIn=a,Gr}var Xr={},It;function ii(){if(It)return Xr;It=1;const n=Dt();function r(t){const s=[];for(;t;)s.push(...n.getSymbols(t)),t=Object.getPrototypeOf(t);return s}return Xr.getSymbolsIn=r,Xr}var $t;function si(){if($t)return Ur;$t=1;const n=kt(),r=_(),t=Et(),s=Qn(),i=Yn(),a=ni(),f=ii();function c(o,...l){if(o==null)return{};l=s.flatten(l);const g=y(o,l);for(let h=0;h<l.length;h++){let m=l[h];switch(typeof m){case"object":Array.isArray(m)||(m=Array.from(m));for(let q=0;q<m.length;q++){const d=m[q];i.unset(g,d)}break;case"string":case"symbol":case"number":i.unset(g,m);break}}return g}function y(o,l){return l.some(g=>Array.isArray(g)||r.isDeepKey(g))?e(o):u(o)}function u(o){const l={},g=[...a.keysIn(o),...f.getSymbolsIn(o)];for(let h=0;h<g.length;h++){const m=g[h];l[m]=o[m]}return l}function e(o){const l={},g=[...a.keysIn(o),...f.getSymbolsIn(o)];for(let h=0;h<g.length;h++){const m=g[h];l[m]=t.cloneDeepWith(o[m],q=>{if(!n.isPlainObject(q))return q})}return l}return Ur.omit=c,Ur}var Jr,Bt;function ui(){return Bt||(Bt=1,Jr=si().omit),Jr}var ai=ui();const Bi=A(ai);var Qr={},Ot;function oi(){if(Ot)return Qr;Ot=1;const n=D();function r(t,s){if(!t||!t.length)return 0;s!=null&&(s=n.iteratee(s));let i;for(let a=0;a<t.length;a++){const f=s?s(t[a]):t[a];f!==void 0&&(i===void 0?i=f:i+=f)}return i}return Qr.sumBy=r,Qr}var Yr,_t;function fi(){return _t||(_t=1,Yr=oi().sumBy),Yr}var ci=fi();const Oi=A(ci);export{Ai as a,Oi as b,gi as c,Xt as d,Qt as e,li as f,qi as g,Ii as i,$i as l,bi as m,Bi as o,pi as r,mi as s,di as t,hi as u};
package/dist/index.html CHANGED
@@ -15,9 +15,8 @@
15
15
  }
16
16
  }
17
17
  </script>
18
- <script type="module" crossorigin src="/assets/index-4xDvXGZ_.js"></script>
19
- <link rel="stylesheet" crossorigin href="/assets/vendor-reveal-DcQQzuI9.css">
20
- <link rel="stylesheet" crossorigin href="/assets/index-CaJDJGky.css">
18
+ <script type="module" crossorigin src="/assets/index-BxA9vp--.js"></script>
19
+ <link rel="stylesheet" crossorigin href="/assets/index-CATki2cp.css">
21
20
  </head>
22
21
  <body>
23
22
  <div id="root"></div>
package/dist/server.cjs CHANGED
@@ -973,8 +973,8 @@ function wrapCommandBus(commandBus, tracker, pluginId, manifestId) {
973
973
  throw e;
974
974
  }
975
975
  }),
976
- setInterceptor: createSafeFunction((interceptor) => {
977
- return commandBus.setInterceptor(interceptor);
976
+ setInterceptor: createSafeFunction((_interceptor) => {
977
+ throw new Error("[Security] setInterceptor cannot be configured from PluginContext");
978
978
  }),
979
979
  unregisterHandler: createSafeFunction((commandType) => {
980
980
  return commandBus.unregisterHandler(resolveType(commandType));
@@ -2506,8 +2506,8 @@ parentPort.on('message', async function(msg) {
2506
2506
  createCommand: function(type, payload, actorId, metadata) {
2507
2507
  return rawCommandBus.createCommand(type, payload, actorId, metadata);
2508
2508
  },
2509
- setInterceptor: function(interceptor) {
2510
- return rawCommandBus.setInterceptor(interceptor);
2509
+ setInterceptor: function(_interceptor) {
2510
+ throw new Error('[Security] setInterceptor cannot be configured from Worker PluginContext');
2511
2511
  }
2512
2512
  } : undefined;
2513
2513
 
@@ -8057,7 +8057,7 @@ var PluginRuntimeComposition = class {
8057
8057
  this.workerManager = workerManager;
8058
8058
  this.id = "srv_plugin_runtime_composition";
8059
8059
  this.name = "PluginRuntimeComposition";
8060
- this.version = "2.5.0";
8060
+ this.version = "0.2.3";
8061
8061
  this._isStarted = false;
8062
8062
  }
8063
8063
  get isStarted() {
@@ -8111,7 +8111,7 @@ var PluginLifecycleManager = class {
8111
8111
  this.pluginHost = pluginHost;
8112
8112
  this.id = "srv_plugin_lifecycle_manager";
8113
8113
  this.name = "PluginLifecycleManager";
8114
- this.version = "2.5.0";
8114
+ this.version = "0.2.3";
8115
8115
  }
8116
8116
  getPluginState(pluginId) {
8117
8117
  return this.pluginHost.getPluginState(pluginId);
@@ -8158,7 +8158,7 @@ var PluginCapabilityGateway = class {
8158
8158
  this.capabilityRegistry = capabilityRegistry;
8159
8159
  this.id = "srv_plugin_capability_gateway";
8160
8160
  this.name = "PluginCapabilityGateway";
8161
- this.version = "2.5.0";
8161
+ this.version = "0.2.3";
8162
8162
  }
8163
8163
  listCapabilities() {
8164
8164
  const rawCaps = this.capabilityRegistry.listCapabilities();
@@ -8212,7 +8212,7 @@ var UnifiedExtensionRegistry = class {
8212
8212
  constructor() {
8213
8213
  this.id = "srv_unified_extension_registry";
8214
8214
  this.name = "UnifiedExtensionRegistry";
8215
- this.version = "2.5.0";
8215
+ this.version = "0.2.3";
8216
8216
  this._extensions = /* @__PURE__ */ new Map();
8217
8217
  }
8218
8218
  registerExtension(category, id, impl, meta) {
@@ -8317,7 +8317,7 @@ var PluginDistributionManager = class {
8317
8317
  this.pluginHost = pluginHost;
8318
8318
  this.id = "srv_plugin_distribution_manager";
8319
8319
  this.name = "PluginDistributionManager";
8320
- this.version = "2.5.0";
8320
+ this.version = "0.2.3";
8321
8321
  this._repositories = /* @__PURE__ */ new Map();
8322
8322
  }
8323
8323
  registerRepository(repo) {
@@ -8406,7 +8406,7 @@ function validatePluginStateTransition(currentState, nextState, pluginId) {
8406
8406
  }
8407
8407
  var ACTIVATION_TIMEOUT_MS = 5e3;
8408
8408
  var DEACTIVATION_TIMEOUT_MS = 5e3;
8409
- var OPENLEARN_VERSION = "2.5.0";
8409
+ var OPENLEARN_VERSION = "0.2.3";
8410
8410
  var PluginHost = class {
8411
8411
  constructor(serviceRegistry, esmLoader, db2, pluginsDir) {
8412
8412
  this.serviceRegistry = serviceRegistry;
@@ -16020,7 +16020,7 @@ var StartupTimeoutError = class extends PlatformBootstrapError {
16020
16020
  this.name = "StartupTimeoutError";
16021
16021
  }
16022
16022
  };
16023
- var PLATFORM_VERSION = "2.5.0";
16023
+ var PLATFORM_VERSION = "0.2.3";
16024
16024
  var BOOTSTRAP_STAGE_NAMES = Object.freeze([
16025
16025
  "Created" /* Created */,
16026
16026
  "Configuring" /* Configuring */,
@@ -18383,6 +18383,26 @@ function getActorId(req) {
18383
18383
  return "user-frontend";
18384
18384
  }
18385
18385
  }
18386
+ function requireAuth(...roles) {
18387
+ return (req, res, next) => {
18388
+ const token = getCookieToken(req);
18389
+ if (!token) return res.status(401).json({ success: false, error: "Authentication required" });
18390
+ const session = getValidSession(token);
18391
+ if (!session) return res.status(401).json({ success: false, error: "Session expired or invalid" });
18392
+ if (roles.length > 0) {
18393
+ let userRole = session.role;
18394
+ if (session.username === "admin" || session.userId === "usr_admin" || userRole === "admin") {
18395
+ userRole = "administrator";
18396
+ }
18397
+ const effectiveRoles = roles.map((r) => r === "admin" ? "administrator" : r);
18398
+ if (!effectiveRoles.includes(userRole)) {
18399
+ return res.status(403).json({ success: false, error: `Role ${session.role} not allowed. Required: ${roles.join(", ")}` });
18400
+ }
18401
+ }
18402
+ req.session = session;
18403
+ next();
18404
+ };
18405
+ }
18386
18406
  function checkIsTeacherOrAdmin(req) {
18387
18407
  const token = getCookieToken(req);
18388
18408
  if (!token) return false;
@@ -20079,7 +20099,8 @@ function registerBridgeRoutes(ctx) {
20079
20099
  res.setHeader("Access-Control-Allow-Origin", "*");
20080
20100
  res.send(BRIDGE_SDK_CODE);
20081
20101
  });
20082
- app.get("/runtime/:uuid", (req, res) => {
20102
+ app.get("/runtime/:uuid", (req, res, next) => {
20103
+ if (req.path.endsWith("/")) return next();
20083
20104
  res.redirect(`/runtime/${req.params.uuid}/`);
20084
20105
  });
20085
20106
  app.get("/runtime/:uuid/*", (req, res) => {
@@ -20139,6 +20160,7 @@ function registerBridgeRoutes(ctx) {
20139
20160
 
20140
20161
  // server/routes/lessons.ts
20141
20162
  var import_genai3 = require("@google/genai");
20163
+ var import_uuid16 = require("uuid");
20142
20164
  function registerLessonsRoutes(ctx) {
20143
20165
  const {
20144
20166
  app,
@@ -20548,6 +20570,72 @@ Provide a short, friendly, and helpful hint (1-2 sentences) directly related to
20548
20570
  res.status(500).json({ error: e.message });
20549
20571
  }
20550
20572
  });
20573
+ app.delete("/api/lessons/:id", async (req, res) => {
20574
+ try {
20575
+ const { id } = req.params;
20576
+ kernelContainer.db.prepare("DELETE FROM whiteboard_elements WHERE lesson_id = ?").run(id);
20577
+ kernelContainer.db.prepare("DELETE FROM student_lesson_progress WHERE lesson_id = ?").run(id);
20578
+ kernelContainer.db.prepare("DELETE FROM schedules WHERE lesson_id = ?").run(id);
20579
+ kernelContainer.db.prepare("DELETE FROM assignments WHERE lesson_id = ?").run(id);
20580
+ const result = kernelContainer.db.prepare("DELETE FROM lessons WHERE id = ?").run(id);
20581
+ if (result.changes === 0) {
20582
+ return res.status(404).json({ error: "Lesson not found" });
20583
+ }
20584
+ res.json({ success: true });
20585
+ } catch (e) {
20586
+ res.status(500).json({ error: e.message });
20587
+ }
20588
+ });
20589
+ app.get("/api/lessons/:id/stats", (req, res) => {
20590
+ try {
20591
+ const { id } = req.params;
20592
+ const whiteboardCount = kernelContainer.db.prepare(
20593
+ "SELECT COUNT(*) as count FROM whiteboard_elements WHERE lesson_id = ?"
20594
+ ).get(id).count;
20595
+ const scheduleCount = kernelContainer.db.prepare(
20596
+ "SELECT COUNT(*) as count FROM schedules WHERE lesson_id = ?"
20597
+ ).get(id).count;
20598
+ const enrollmentCount = kernelContainer.db.prepare(
20599
+ "SELECT COUNT(*) as count FROM student_lesson_progress WHERE lesson_id = ?"
20600
+ ).get(id).count;
20601
+ const assignmentCount = kernelContainer.db.prepare(
20602
+ "SELECT COUNT(*) as count FROM assignments WHERE lesson_id = ?"
20603
+ ).get(id).count;
20604
+ res.json({ whiteboardCount, scheduleCount, enrollmentCount, assignmentCount });
20605
+ } catch (e) {
20606
+ res.status(500).json({ error: e.message });
20607
+ }
20608
+ });
20609
+ app.post("/api/lessons/:id/clone", async (req, res) => {
20610
+ try {
20611
+ const { id } = req.params;
20612
+ const original = kernelContainer.db.prepare("SELECT * FROM lessons WHERE id = ?").get(id);
20613
+ if (!original) {
20614
+ return res.status(404).json({ error: "Lesson not found" });
20615
+ }
20616
+ const newId = (0, import_uuid16.v7)();
20617
+ const now = Date.now();
20618
+ const newTitle = `\u526F\u672C-${original.title}`;
20619
+ kernelContainer.db.prepare(
20620
+ "INSERT INTO lessons (id, title, content, timeline, progress_mode, progress_conditions, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
20621
+ ).run(newId, newTitle, original.content, original.timeline, original.progress_mode, original.progress_conditions, now, now);
20622
+ const whiteboardElements = kernelContainer.db.prepare(
20623
+ "SELECT * FROM whiteboard_elements WHERE lesson_id = ?"
20624
+ ).all(id);
20625
+ const insertElement = kernelContainer.db.prepare(
20626
+ "INSERT INTO whiteboard_elements (id, lesson_id, type, data, created_at) VALUES (?, ?, ?, ?, ?)"
20627
+ );
20628
+ for (const el of whiteboardElements) {
20629
+ insertElement.run((0, import_uuid16.v7)(), newId, el.type, el.data, now);
20630
+ }
20631
+ const cloned = kernelContainer.db.prepare(
20632
+ "SELECT l.*, 0 as enrollment_count FROM lessons l WHERE l.id = ?"
20633
+ ).get(newId);
20634
+ res.json({ success: true, lesson: cloned });
20635
+ } catch (e) {
20636
+ res.status(500).json({ error: e.message });
20637
+ }
20638
+ });
20551
20639
  }
20552
20640
 
20553
20641
  // server/routes/workspace.ts
@@ -20792,7 +20880,7 @@ function registerAdminRoutes(ctx) {
20792
20880
  runGeminiAgentChat: runGeminiAgentChat2,
20793
20881
  runOpenAIAgentChat: runOpenAIAgentChat2
20794
20882
  } = ctx;
20795
- app.post("/api/admin/seed-demo", (req, res) => {
20883
+ app.post("/api/admin/seed-demo", requireAuth("administrator"), (req, res) => {
20796
20884
  try {
20797
20885
  const db2 = kernelContainer.db;
20798
20886
  const DEMO_CLASS_ID = "demo-class";
@@ -20808,7 +20896,7 @@ function registerAdminRoutes(ctx) {
20808
20896
  db2.prepare("INSERT INTO classes (id, name, description, created_at) VALUES (?, ?, ?, ?)").run(
20809
20897
  DEMO_CLASS_ID,
20810
20898
  "\u4EBA\u5DE5\u667A\u80FD\u4E0E\u521B\u610F\u7F16\u7A0B\u793A\u8303\u73ED",
20811
- "\u8FD9\u662F\u7CFB\u7EDF\u521D\u59CB\u5316\u7684\u793A\u4F8B\u8BFE\u7A0B\u73ED\u7EA7\uFF0C\u7528\u4E8E\u6559\u5B66\u4F53\u9A8C\uFFFD?",
20899
+ "\u8FD9\u662F\u7CFB\u7EDF\u521D\u59CB\u5316\u7684\u793A\u4F8B\u8BFE\u7A0B\u73ED\u7EA7\uFF0C\u7528\u4E8E\u6559\u5B66\u4F53\u9A8C?",
20812
20900
  Date.now()
20813
20901
  );
20814
20902
  }
@@ -20836,7 +20924,7 @@ function registerAdminRoutes(ctx) {
20836
20924
  lessonId = "demo-lesson";
20837
20925
  db2.prepare("INSERT INTO lessons (id, title, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?)").run(
20838
20926
  lessonId,
20839
- "\u521D\u8BC6 Python\uFF1A\u667A\u80FD\u767D\u677F\u521B\u610F\u7F16\uFFFD?",
20927
+ "\u521D\u8BC6 Python\uFF1A\u667A\u80FD\u767D\u677F\u521B\u610F\u7F16?",
20840
20928
  JSON.stringify({ elements: [] }),
20841
20929
  Date.now(),
20842
20930
  Date.now()
@@ -20858,7 +20946,7 @@ function registerAdminRoutes(ctx) {
20858
20946
  res.status(500).json({ error: e.message });
20859
20947
  }
20860
20948
  });
20861
- app.post("/api/classes/import", (req, res) => {
20949
+ app.post("/api/classes/import", requireAuth("teacher", "administrator"), (req, res) => {
20862
20950
  try {
20863
20951
  const { classes } = req.body;
20864
20952
  if (!classes || !Array.isArray(classes)) {
@@ -20908,7 +20996,7 @@ function registerAdminRoutes(ctx) {
20908
20996
  res.status(500).json({ error: e.message });
20909
20997
  }
20910
20998
  });
20911
- app.post("/api/students/import", (req, res) => {
20999
+ app.post("/api/students/import", requireAuth("teacher", "administrator"), (req, res) => {
20912
21000
  try {
20913
21001
  const { students } = req.body;
20914
21002
  if (!students || !Array.isArray(students)) {
@@ -21507,16 +21595,16 @@ function registerRosterRoutes(ctx) {
21507
21595
  res.status(550).json({ error: e.message });
21508
21596
  }
21509
21597
  });
21510
- app.get("/api/users", async (req, res) => {
21598
+ app.get("/api/users", requireAuth("administrator"), async (req, res) => {
21511
21599
  try {
21512
- const cmd = kernelContainer.commandBus.createCommand("user.list", {}, "user-demo");
21600
+ const cmd = kernelContainer.commandBus.createCommand("user.list", {}, getActorId(req));
21513
21601
  const users = await kernelContainer.commandBus.execute(cmd);
21514
21602
  res.json(users);
21515
21603
  } catch (e) {
21516
21604
  res.status(550).json({ error: e.message });
21517
21605
  }
21518
21606
  });
21519
- app.post("/api/users", async (req, res) => {
21607
+ app.post("/api/users", requireAuth("administrator"), async (req, res) => {
21520
21608
  try {
21521
21609
  const { username, password, role, name, status = "active" } = req.body;
21522
21610
  const cmd = kernelContainer.commandBus.createCommand("user.create", {
@@ -21525,14 +21613,14 @@ function registerRosterRoutes(ctx) {
21525
21613
  role,
21526
21614
  name,
21527
21615
  status
21528
- }, "user-demo");
21616
+ }, getActorId(req));
21529
21617
  const result = await kernelContainer.commandBus.execute(cmd);
21530
21618
  res.json(result);
21531
21619
  } catch (e) {
21532
21620
  res.status(550).json({ error: e.message });
21533
21621
  }
21534
21622
  });
21535
- app.put("/api/users/:id", async (req, res) => {
21623
+ app.put("/api/users/:id", requireAuth("administrator"), async (req, res) => {
21536
21624
  try {
21537
21625
  const { username, role, name, password, status } = req.body;
21538
21626
  const cmd = kernelContainer.commandBus.createCommand("user.update", {
@@ -21542,18 +21630,18 @@ function registerRosterRoutes(ctx) {
21542
21630
  name,
21543
21631
  password,
21544
21632
  status
21545
- }, "user-demo");
21633
+ }, getActorId(req));
21546
21634
  const result = await kernelContainer.commandBus.execute(cmd);
21547
21635
  res.json(result);
21548
21636
  } catch (e) {
21549
21637
  res.status(550).json({ error: e.message });
21550
21638
  }
21551
21639
  });
21552
- app.delete("/api/users/:id", async (req, res) => {
21640
+ app.delete("/api/users/:id", requireAuth("administrator"), async (req, res) => {
21553
21641
  try {
21554
21642
  const cmd = kernelContainer.commandBus.createCommand("user.delete", {
21555
21643
  userId: req.params.id
21556
- }, "user-demo");
21644
+ }, getActorId(req));
21557
21645
  const result = await kernelContainer.commandBus.execute(cmd);
21558
21646
  res.json(result);
21559
21647
  } catch (e) {
@@ -21568,7 +21656,7 @@ function registerRosterRoutes(ctx) {
21568
21656
  res.status(500).json({ error: e.message });
21569
21657
  }
21570
21658
  });
21571
- app.post("/api/labs", (req, res) => {
21659
+ app.post("/api/labs", requireAuth("teacher", "administrator"), (req, res) => {
21572
21660
  try {
21573
21661
  const { room_number, rows, cols } = req.body;
21574
21662
  const id = "lab_" + Math.random().toString(36).slice(2, 10);
@@ -21580,7 +21668,7 @@ function registerRosterRoutes(ctx) {
21580
21668
  res.status(500).json({ error: e.message });
21581
21669
  }
21582
21670
  });
21583
- app.put("/api/labs/:id", (req, res) => {
21671
+ app.put("/api/labs/:id", requireAuth("teacher", "administrator"), (req, res) => {
21584
21672
  try {
21585
21673
  const { room_number, rows, cols } = req.body;
21586
21674
  kernelContainer.db.prepare(
@@ -21591,7 +21679,7 @@ function registerRosterRoutes(ctx) {
21591
21679
  res.status(500).json({ error: e.message });
21592
21680
  }
21593
21681
  });
21594
- app.delete("/api/labs/:id", (req, res) => {
21682
+ app.delete("/api/labs/:id", requireAuth("teacher", "administrator"), (req, res) => {
21595
21683
  try {
21596
21684
  kernelContainer.db.prepare("DELETE FROM computer_labs WHERE id = ?").run(req.params.id);
21597
21685
  kernelContainer.db.prepare("DELETE FROM student_seats WHERE lab_id = ?").run(req.params.id);
@@ -21610,7 +21698,7 @@ function registerRosterRoutes(ctx) {
21610
21698
  res.status(500).json({ error: e.message });
21611
21699
  }
21612
21700
  });
21613
- app.post("/api/classes/:classId/seats", (req, res) => {
21701
+ app.post("/api/classes/:classId/seats", requireAuth("teacher", "administrator"), (req, res) => {
21614
21702
  try {
21615
21703
  const { lab_id, seats } = req.body;
21616
21704
  kernelContainer.db.prepare("UPDATE classes SET lab_id = ? WHERE id = ?").run(lab_id || null, req.params.classId);
@@ -21808,7 +21896,7 @@ function registerRosterRoutes(ctx) {
21808
21896
  res.status(500).json({ error: e.message });
21809
21897
  }
21810
21898
  });
21811
- app.post("/api/classes/:id/students/bulk-enroll", (req, res) => {
21899
+ app.post("/api/classes/:id/students/bulk-enroll", requireAuth("teacher", "administrator"), (req, res) => {
21812
21900
  try {
21813
21901
  const { students } = req.body;
21814
21902
  const classId = req.params.id;
@@ -22256,9 +22344,9 @@ Provide a grade score (0-100) and brief feedback. Ensure you output in this exac
22256
22344
  } catch (e) {
22257
22345
  }
22258
22346
  }
22259
- const { v7: uuidv716 } = await import("uuid");
22347
+ const { v7: uuidv717 } = await import("uuid");
22260
22348
  await kernelContainer.commandBus.execute({
22261
- id: uuidv716(),
22349
+ id: uuidv717(),
22262
22350
  type: "ai.apply_grade",
22263
22351
  actorId: "system",
22264
22352
  timestamp: Date.now(),
@@ -23353,6 +23441,28 @@ async function checkVersion(source, installedVersion) {
23353
23441
  }
23354
23442
 
23355
23443
  // server/routes/plugins.ts
23444
+ function isSafeExternalUrl(urlStr) {
23445
+ try {
23446
+ const parsed = new URL(urlStr);
23447
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
23448
+ return { safe: false, reason: "Only HTTP and HTTPS protocols are allowed" };
23449
+ }
23450
+ const hostname = parsed.hostname.toLowerCase();
23451
+ if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname.endsWith(".local") || hostname === "0.0.0.0" || hostname === "::1" || hostname === "[::1]") {
23452
+ return { safe: false, reason: "Access to loopback/local addresses is forbidden" };
23453
+ }
23454
+ const ipv4Match = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
23455
+ if (ipv4Match) {
23456
+ const octets = ipv4Match.slice(1).map(Number);
23457
+ if (octets[0] === 127 || octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168 || octets[0] === 169 && octets[1] === 254 || octets[0] === 0 || octets[0] >= 224) {
23458
+ return { safe: false, reason: "Access to private or link-local IP addresses is forbidden" };
23459
+ }
23460
+ }
23461
+ return { safe: true };
23462
+ } catch (e) {
23463
+ return { safe: false, reason: `Invalid URL format: ${e.message}` };
23464
+ }
23465
+ }
23356
23466
  function registerPluginsRoutes(ctx) {
23357
23467
  const {
23358
23468
  app,
@@ -23500,12 +23610,19 @@ function registerPluginsRoutes(ctx) {
23500
23610
  res.status(500).json({ success: false, error: e.message });
23501
23611
  }
23502
23612
  });
23503
- app.post("/api/plugins/:id(*)/one-click-update", async (req, res) => {
23613
+ app.post("/api/plugins/:id(*)/one-click-update", requireAuth("administrator"), async (req, res) => {
23504
23614
  try {
23505
23615
  const targetPluginId = decodeURIComponent(req.params.id);
23506
23616
  const { downloadUrl } = req.body || {};
23507
23617
  let zipBuffer;
23508
23618
  if (downloadUrl) {
23619
+ const urlCheck = isSafeExternalUrl(downloadUrl);
23620
+ if (!urlCheck.safe) {
23621
+ return res.status(400).json({
23622
+ success: false,
23623
+ error: `\u5B89\u5168\u62E6\u622A: \u975E\u6CD5\u4E0B\u8F7D\u5730\u5740 (${urlCheck.reason})`
23624
+ });
23625
+ }
23509
23626
  try {
23510
23627
  const resp = await fetch(downloadUrl, {
23511
23628
  headers: { "User-Agent": "OpenLearnV2-PluginUpdater/1.0" },
@@ -23583,7 +23700,7 @@ function registerPluginsRoutes(ctx) {
23583
23700
  res.status(500).json({ success: false, error: e.message });
23584
23701
  }
23585
23702
  });
23586
- app.post("/api/plugins/:id(*)/config", (req, res) => {
23703
+ app.post("/api/plugins/:id(*)/config", requireAuth("administrator"), (req, res) => {
23587
23704
  try {
23588
23705
  const rawId = decodeURIComponent(req.params.id);
23589
23706
  const pluginId = kernelContainer.pluginHost.resolvePluginUuid(rawId);
@@ -23602,7 +23719,7 @@ function registerPluginsRoutes(ctx) {
23602
23719
  res.status(500).json({ success: false, error: e.message });
23603
23720
  }
23604
23721
  });
23605
- app.post("/api/plugins/:id(*)/toggle", async (req, res) => {
23722
+ app.post("/api/plugins/:id(*)/toggle", requireAuth("administrator"), async (req, res) => {
23606
23723
  try {
23607
23724
  const rawId = decodeURIComponent(req.params.id);
23608
23725
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23616,7 +23733,7 @@ function registerPluginsRoutes(ctx) {
23616
23733
  res.status(500).json({ success: false, error: err.message });
23617
23734
  }
23618
23735
  });
23619
- app.delete("/api/plugins/:id(*)", async (req, res) => {
23736
+ app.delete("/api/plugins/:id(*)", requireAuth("administrator"), async (req, res) => {
23620
23737
  try {
23621
23738
  const rawId = decodeURIComponent(req.params.id);
23622
23739
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23644,7 +23761,7 @@ function registerPluginsRoutes(ctx) {
23644
23761
  res.status(404).json({ success: false, error: err.message });
23645
23762
  }
23646
23763
  });
23647
- app.post("/api/plugins", async (req, res) => {
23764
+ app.post("/api/plugins", requireAuth("administrator"), async (req, res) => {
23648
23765
  try {
23649
23766
  const { sourceCode } = req.body;
23650
23767
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23659,7 +23776,7 @@ function registerPluginsRoutes(ctx) {
23659
23776
  res.status(500).json({ success: false, error: err.message });
23660
23777
  }
23661
23778
  });
23662
- app.post("/api/plugins/upload-zip", async (req, res) => {
23779
+ app.post("/api/plugins/upload-zip", requireAuth("administrator"), async (req, res) => {
23663
23780
  try {
23664
23781
  const { base64Data, filename, executionMode } = req.body;
23665
23782
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23674,7 +23791,7 @@ function registerPluginsRoutes(ctx) {
23674
23791
  res.status(500).json({ success: false, error: err.message });
23675
23792
  }
23676
23793
  });
23677
- app.post("/api/plugins/upload-zip-raw", import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }), async (req, res) => {
23794
+ app.post("/api/plugins/upload-zip-raw", requireAuth("administrator"), import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }), async (req, res) => {
23678
23795
  try {
23679
23796
  const zipBuffer = req.body;
23680
23797
  const filename = req.headers["x-filename"] ? decodeURIComponent(req.headers["x-filename"]) : "plugin.zip";
@@ -23718,6 +23835,7 @@ function registerPluginsRoutes(ctx) {
23718
23835
  });
23719
23836
  app.post(
23720
23837
  "/api/plugins/:id(*)/update-zip-raw",
23838
+ requireAuth("administrator"),
23721
23839
  import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }),
23722
23840
  async (req, res) => {
23723
23841
  try {
@@ -23804,7 +23922,7 @@ function registerPluginsRoutes(ctx) {
23804
23922
  res.status(500).json({ error: e.message });
23805
23923
  }
23806
23924
  });
23807
- app.post("/api/ai-providers", (req, res) => {
23925
+ app.post("/api/ai-providers", requireAuth("administrator"), (req, res) => {
23808
23926
  try {
23809
23927
  const { name, api_url, api_key, model_name } = req.body;
23810
23928
  if (!name || !api_url || !model_name) {
@@ -23819,7 +23937,7 @@ function registerPluginsRoutes(ctx) {
23819
23937
  res.status(500).json({ error: e.message });
23820
23938
  }
23821
23939
  });
23822
- app.put("/api/ai-providers/:id", (req, res) => {
23940
+ app.put("/api/ai-providers/:id", requireAuth("administrator"), (req, res) => {
23823
23941
  try {
23824
23942
  const { name, api_url, api_key, model_name } = req.body;
23825
23943
  if (!name || !api_url || !model_name) {
@@ -23839,7 +23957,7 @@ function registerPluginsRoutes(ctx) {
23839
23957
  res.status(500).json({ error: e.message });
23840
23958
  }
23841
23959
  });
23842
- app.delete("/api/ai-providers/:id", (req, res) => {
23960
+ app.delete("/api/ai-providers/:id", requireAuth("administrator"), (req, res) => {
23843
23961
  try {
23844
23962
  kernelContainer.db.prepare("DELETE FROM ai_providers WHERE id = ?").run(req.params.id);
23845
23963
  res.json({ success: true });
@@ -23859,7 +23977,7 @@ function registerPluginsRoutes(ctx) {
23859
23977
  res.status(500).json({ error: e.message });
23860
23978
  }
23861
23979
  });
23862
- app.put("/api/site-settings", (req, res) => {
23980
+ app.put("/api/site-settings", requireAuth("administrator"), (req, res) => {
23863
23981
  try {
23864
23982
  const { siteName, slogan, logoUrl } = req.body || {};
23865
23983
  kernelContainer.db.prepare(
@@ -23874,7 +23992,7 @@ function registerPluginsRoutes(ctx) {
23874
23992
  res.status(500).json({ error: e.message });
23875
23993
  }
23876
23994
  });
23877
- app.post("/api/ai-providers/test", async (req, res) => {
23995
+ app.post("/api/ai-providers/test", requireAuth("administrator"), async (req, res) => {
23878
23996
  try {
23879
23997
  const { api_url, api_key: providedKey, model_name } = req.body;
23880
23998
  if (!api_url || !model_name) {
@@ -23975,8 +24093,8 @@ async function startServer() {
23975
24093
  standardHeaders: true,
23976
24094
  legacyHeaders: false
23977
24095
  });
23978
- app.use(import_express3.default.json({ limit: "400mb" }));
23979
- app.use(import_express3.default.urlencoded({ limit: "400mb", extended: true }));
24096
+ app.use(import_express3.default.json({ limit: "10mb" }));
24097
+ app.use(import_express3.default.urlencoded({ limit: "10mb", extended: true }));
23980
24098
  app.use("/uploads", import_express3.default.static(import_path14.default.join(process.cwd(), "uploads")));
23981
24099
  app.use("/plugins", import_express3.default.static(import_path14.default.join(process.cwd(), "plugins")));
23982
24100
  app.use((req, res, next) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openlearn-next",
3
- "version": "0.2.2",
3
+ "version": "0.2.5",
4
4
  "private": false,
5
5
  "description": "A plugin-driven Educational OS / LMS platform with AI agent teaching assistant",
6
6
  "keywords": [
@@ -1 +0,0 @@
1
- import{r as m}from"./vendor-konva-GivUq6dt.js";import{j as e,G as h,M as w,a as v,X as y}from"./whiteboard-Dp8tFXTO.js";const j=(function(){const l=typeof document<"u"&&document.createElement("link").relList;return l&&l.supports&&l.supports("modulepreload")?"modulepreload":"preload"})(),E=function(n){return"/"+n},g={},N=function(l,c,f){let i=Promise.resolve();if(c&&c.length>0){let t=function(r){return Promise.all(r.map(a=>Promise.resolve(a).then(u=>({status:"fulfilled",value:u}),u=>({status:"rejected",reason:u}))))};document.getElementsByTagName("link");const s=document.querySelector("meta[property=csp-nonce]"),x=s?.nonce||s?.getAttribute("nonce");i=t(c.map(r=>{if(r=E(r),r in g)return;g[r]=!0;const a=r.endsWith(".css"),u=a?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${r}"]${u}`))return;const o=document.createElement("link");if(o.rel=a?"stylesheet":j,a||(o.as="script"),o.crossOrigin="",o.href=r,x&&o.setAttribute("nonce",x),document.head.appendChild(o),a)return new Promise((p,b)=>{o.addEventListener("load",p),o.addEventListener("error",()=>b(new Error(`Unable to preload CSS for ${r}`)))})}))}function d(t){const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=t,window.dispatchEvent(s),!s.defaultPrevented)throw t}return i.then(t=>{for(const s of t||[])s.status==="rejected"&&d(s.reason);return l().catch(d)})},_=m.lazy(()=>N(()=>Promise.resolve().then(()=>F),void 0).then(n=>({default:n.InteractiveCoursewareViewer}))),P=Object.freeze(Object.defineProperty({__proto__:null,CoursewareViewer:_},Symbol.toStringTag,{value:"Module"}));function S({coursewareId:n,onClose:l}){const[c,f]=m.useState(!1),i=m.useRef(null);m.useEffect(()=>{const t=()=>{f(!!document.fullscreenElement&&document.fullscreenElement===i.current)};return document.addEventListener("fullscreenchange",t),()=>{document.removeEventListener("fullscreenchange",t)}},[]);const d=()=>{const t=i.current;t&&(document.fullscreenElement?document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen&&document.webkitExitFullscreen():t.requestFullscreen?t.requestFullscreen():t.webkitRequestFullscreen&&t.webkitRequestFullscreen())};return n?e.jsxs("div",{ref:i,className:"flex flex-col h-full bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden relative",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-2 bg-gray-100 border-b border-gray-200 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 select-none",children:[e.jsx(h,{size:16,className:"text-indigo-500"}),e.jsx("span",{className:"font-semibold text-sm text-gray-700",children:"Interactive Courseware"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:d,className:"p-1 hover:bg-gray-200 rounded-lg text-gray-500 transition-colors cursor-pointer",title:c?"退出全屏":"全屏播放",children:c?e.jsx(w,{size:16}):e.jsx(v,{size:16})}),l&&e.jsx("button",{onClick:l,className:"p-1 hover:bg-gray-200 rounded-lg text-gray-500 transition-colors cursor-pointer",children:e.jsx(y,{size:16})})]})]}),e.jsx("div",{className:"flex-1 relative bg-white",children:e.jsx("iframe",{src:`/api/courseware/${n}`,sandbox:"allow-scripts allow-same-origin allow-downloads allow-forms",allowFullScreen:!0,className:"w-full h-full border-none",title:"Interactive Courseware"})})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-gray-400 bg-gray-50 rounded-xl border border-dashed border-gray-300",children:[e.jsx(h,{size:48,className:"mb-4 text-gray-300 opacity-50"}),e.jsx("h3",{className:"text-lg font-medium text-gray-700",children:"No Courseware Selected"}),e.jsx("p",{className:"mt-2 text-sm text-center",children:"Please select a courseware from the list to view it interactively."})]})}const F=Object.freeze(Object.defineProperty({__proto__:null,InteractiveCoursewareViewer:S},Symbol.toStringTag,{value:"Module"}));export{N as _,P as i};