@@ -22311,15 +22311,67 @@ async function loadPlugins() {
2231122311 } catch (e) { list.innerHTML = '<div style="color:var(--danger);">Error: ' + escapeHtml(e.message) + '</div>'; }
2231222312}
2231322313
22314- function showInstallPluginModal() {
22315- document.getElementById('plugin-install-url').value = '';
22314+ async function showInstallPluginModal() {
2231622315 const modal = document.getElementById('plugin-install-modal');
2231722316 modal.style.display = 'flex';
2231822317 setTimeout(() => modal.classList.add('active'), 10);
22318+
22319+ // Load store
22320+ const storeList = document.getElementById('plugin-store-list');
22321+ if (storeList) storeList.innerHTML = '<div style="color:var(--text-muted);text-align:center;padding:20px;">Loading plugin store...</div>';
22322+ try {
22323+ const resp = await fetch(apiUrl('/api/plugins/store'));
22324+ if (!resp.ok) {
22325+ const data = await resp.json().catch(() => ({}));
22326+ if (storeList) storeList.innerHTML = `<div style="color:var(--danger);text-align:center;padding:20px;">${escapeHtml(data.error || 'Failed to load store')}</div>`;
22327+ return;
22328+ }
22329+ const plugins = await resp.json();
22330+ if (!Array.isArray(plugins) || plugins.length === 0) {
22331+ if (storeList) storeList.innerHTML = '<div style="color:var(--text-muted);text-align:center;padding:20px;">No plugins available</div>';
22332+ return;
22333+ }
22334+ if (storeList) storeList.innerHTML = plugins.map(p => `
22335+ <div style="display:flex;align-items:center;gap:14px;padding:14px 16px;background:var(--bg-primary);border-radius:10px;border:1px solid var(--border);margin-bottom:8px;">
22336+ <span style="font-size:32px;">${p.icon || '\u{1F50C}'}</span>
22337+ <div style="flex:1;">
22338+ <div style="font-weight:600;font-size:14px;">${escapeHtml(p.name)} <span style="font-size:11px;color:var(--text-muted);font-weight:400;">v${escapeHtml(p.version || '1.0')}</span>
22339+ ${p.enterprise_only ? '<span style="font-size:10px;background:rgba(220,38,38,0.15);color:#ef4444;padding:1px 6px;border-radius:3px;margin-left:6px;">Enterprise</span>' : ''}
22340+ </div>
22341+ <div style="font-size:12px;color:var(--text-secondary);margin-top:3px;line-height:1.5;">${escapeHtml(p.description || '')}</div>
22342+ <div style="font-size:11px;color:var(--text-muted);margin-top:4px;">by ${escapeHtml(p.author || 'Unknown')}</div>
22343+ </div>
22344+ <div>
22345+ ${p.installed
22346+ ? '<span style="font-size:12px;color:var(--success);font-weight:600;">Installed</span>'
22347+ : `<button class="btn btn-sm btn-primary" onclick="installPluginFromStore('${escapeAttr(p.download_url)}', '${escapeAttr(p.name)}')" style="font-size:12px;white-space:nowrap;">Install</button>`
22348+ }
22349+ </div>
22350+ </div>
22351+ `).join('');
22352+ } catch (e) {
22353+ if (storeList) storeList.innerHTML = `<div style="color:var(--danger);text-align:center;padding:20px;">Error: ${escapeHtml(e.message)}</div>`;
22354+ }
22355+ }
22356+
22357+ async function installPluginFromStore(url, name) {
22358+ showToast(`Installing ${name}...`, 'info');
22359+ document.getElementById('plugin-install-modal').style.display = 'none';
22360+ try {
22361+ const resp = await fetch(apiUrl('/api/plugins/install'), {
22362+ method: 'POST', headers: { 'Content-Type': 'application/json' },
22363+ body: JSON.stringify({ url }),
22364+ });
22365+ const data = await resp.json();
22366+ if (!resp.ok) { showToast(data.error || 'Install failed', 'error'); return; }
22367+ showToast(`${name} installed successfully`, 'success');
22368+ loadPlugins();
22369+ loadPluginAssets();
22370+ } catch (e) { showToast('Install failed: ' + e.message, 'error'); }
2231922371}
2232022372
2232122373async function installPlugin() {
22322- const url = document.getElementById('plugin-install-url').value.trim();
22374+ const url = document.getElementById('plugin-install-url')? .value? .trim();
2232322375 if (!url) { showToast('Please enter a plugin URL', 'error'); return; }
2232422376 document.getElementById('plugin-install-modal').style.display = 'none';
2232522377 showToast('Installing plugin...', 'info');
@@ -22332,7 +22384,7 @@ async function installPlugin() {
2233222384 if (!resp.ok) { showToast(data.error || 'Install failed', 'error'); return; }
2233322385 showToast(data.message || 'Plugin installed', 'success');
2233422386 loadPlugins();
22335- loadPluginAssets(); // Load new plugin's frontend
22387+ loadPluginAssets();
2233622388 } catch (e) { showToast('Install failed: ' + e.message, 'error'); }
2233722389}
2233822390
0 commit comments