/* global React */ /* eslint-disable */ const { useState: useStateEX, useEffect: useEffectEX, useRef: useRefEX } = React; /* ---------- Icons ---------- */ const IconEX = { data: () => , chat: () => , rocket: () => , box: () => , server: () => , external: () => , grid: () => , bell: () => , moon: () => , user: () => , logout: () => , sidebar: () => , link: () => , ext: () => , globe: () => , search: () => , eye: () => , trash: () => , lock: () => , }; /* ---------- Sidebar ---------- */ function ExSidebar() { const [progress, setProgress] = useStateEX(window.AIMakerProgress ? window.AIMakerProgress.get() : { modules:{} }); useEffectEX(() => { function onP(e) { setProgress(e.detail); } window.addEventListener('aimaker:progress', onP); return () => window.removeEventListener('aimaker:progress', onP); }, []); const items = [ { id:'data', label: window.t('nav.data'), icon: IconEX.data, link:'AiMaker Dashboard.html', mod:'data' }, { id:'chat', label: window.t('nav.chat'), icon: IconEX.chat, link:'Fablab Chat.html', mod:'fablab' }, { id:'apps', label: window.t('nav.apps'), icon: IconEX.rocket, link:'Gestion des applications.html', mod:'apps' }, { id:'prod', label: window.t('nav.products'), icon: IconEX.box, link:'Produits.html', mod:'products' }, { id:'srv', label: window.t('nav.server'), icon: IconEX.server, link:'Serveur.html', mod:'server' }, { id:'ext', label: window.t('nav.external'), icon: IconEX.external, active:true, mod:'external' }, { id:'work', label: window.t('nav.workspace'), icon: IconEX.grid, link:'Workspace.html', mod:'workspace' }, ]; return ( ); } function ExTopbar() { return (
{window.t('topbar.title')}
); } /* ---------- Initial resources ---------- */ const EXT_INITIAL = [ { id:1, name:'Claude MCP server skills', desc:'Aimaker MCP for use with creation skills copy and paste this url in claude field...', lang:'EN', author:'admin', visibility:'public', date:'19/05/2026', tab:['all','public'] }, { id:2, name:'Pomelli', desc:'', lang:'FR', author:'admin', visibility:'public', date:'19/05/2026', tab:['all','public'] }, { id:3, name:'PLAUD', desc:'pagina para transcripcion de video a texto', lang:'EN', author:'admin', visibility:'public', date:'14/05/2026', tab:['all','public'] }, { id:4, name:'Reachy mini', desc:'Robot open-source assistant para experimentación con IA', lang:'EN', author:'admin', visibility:'public', date:'12/05/2026', tab:['all','public'] }, ]; /* ---------- Page ---------- */ function ExternalPage() { const [items, setItems] = useStateEX(EXT_INITIAL); const [tab, setTab] = useStateEX('all'); const [query, setQuery] = useStateEX(''); const [showCreate, setShowCreate] = useStateEX(false); const [lastNewId, setLastNewId] = useStateEX(null); const [toast, setToast] = useStateEX(null); // Sim tracking const [created, setCreated] = useStateEX(0); const [madePublic, setMadePublic] = useStateEX(false); useEffectEX(() => { window.dispatchEvent(new CustomEvent('aimy:exState', { detail: { created, madePublic }})); }, [created, madePublic]); const visible = items.filter(it => { if (tab === 'all') return true; if (tab === 'mine') return it.author === 'tu'; if (tab === 'public') return it.visibility === 'public'; if (tab === 'private') return it.visibility === 'private'; if (tab === 'shared') return it.shared; return true; }).filter(it => !query.trim() ? true : (it.name + ' ' + it.desc).toLowerCase().includes(query.toLowerCase())); function addItem(payload) { const id = Date.now(); const item = { id, name: payload.name, desc: payload.desc, lang: payload.lang, author: 'tu', visibility: payload.visibility, date: new Date().toLocaleDateString('fr-FR'), }; setItems(prev => [item, ...prev]); setLastNewId(id); setShowCreate(false); setCreated(c => c + 1); setToast({ kind:'create', name: payload.name, visibility: payload.visibility }); setTimeout(() => setToast(null), 3000); } function toggleVisibility(it) { const next = it.visibility === 'public' ? 'private' : 'public'; setItems(prev => prev.map(x => x.id === it.id ? { ...x, visibility: next } : x)); if (it.author === 'tu' && next === 'public' && !madePublic) { setMadePublic(true); } setToast({ kind:'vis', name: it.name, visibility: next }); setTimeout(() => setToast(null), 3000); } function removeItem(id) { setItems(prev => prev.filter(x => x.id !== id)); } return (

{window.t('ext.title')}

{window.t('ext.subtitle')}

setQuery(e.target.value)} placeholder={window.t('ext.search.placeholder')}/>
{window.t('ext.type.all')}
{[ {id:'all', key:'ext.tab.all'}, {id:'mine', key:'ext.tab.mine'}, {id:'shared', key:'ext.tab.shared'}, {id:'public', key:'ext.tab.public'}, {id:'private', key:'ext.tab.private'}, ].map(tb => ( ))}
{visible.length === 0 && ( )} {visible.map(it => ( ))}
{window.t('ext.col.type')} {window.t('ext.col.name')} {window.t('ext.col.lang')} {window.t('ext.col.action')} {window.t('ext.col.vis')} {window.t('ext.col.author')}
🔗
{window.t('ext.empty.title')}
{window.t('ext.empty.hint')}
{window.t('ext.type.label')}
{it.name}
{it.desc &&
{it.desc}
}
{it.lang}
{it.visibility === 'public' ? 'Public' : 'Privé'} toggleVisibility(it)} title="Cliquer pour basculer"> {it.visibility === 'public' ? 'Public' : 'Privé'}
{it.author === 'tu' ? 'tu' : 'ad'}
{it.author}
{it.date}
{showCreate && setShowCreate(false)} onCreate={addItem}/>} {toast && (
{toast.kind === 'create' && <>✅ {toast.name} creado · visibilidad: {toast.visibility}} {toast.kind === 'vis' && <>🌐 {toast.name} ahora es {toast.visibility}{toast.visibility === 'public' ? ' · ¡compartido con la comunidad!' : ''}}
)}
); } function CreateLinkModal({ onCancel, onCreate }) { const [form, setForm] = useStateEX({ name:'', url:'', desc:'', lang:'ES', visibility:'private' }); const valid = form.name.trim() && form.url.trim(); return (
e.stopPropagation()} data-tour="ext-modal">

{window.t('ext.modal.title')}

{window.t('ext.modal.sub')}

setForm(f=>({...f, name:e.target.value}))} className="input"/>
setForm(f=>({...f, url:e.target.value}))} className="input" placeholder="https://..."/>