Feat v0.5.0 realtime dialog (#30)
All checks were successful
All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #30.
This commit is contained in:
@@ -29,6 +29,8 @@ function sourceBadge(source) {
|
||||
|
||||
function statusBadge(status) {
|
||||
if (status === 'dormant') return html`<span class="badge" style="opacity:0.6;">dormant</span>`;
|
||||
if (status === 'pending_review') return html`<span class="badge" style="background:var(--warning,#e6a817);color:#000;">review</span>`;
|
||||
if (status === 'suspended') return html`<span class="badge" style="background:var(--danger,#d33);color:#fff;">suspended</span>`;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -43,6 +45,8 @@ export default function PackagesSection() {
|
||||
const [registryPkgs, setRegistryPkgs] = useState([]);
|
||||
const [registryLoading, setRegistryLoading] = useState(false);
|
||||
const [installing, setInstalling] = useState(false);
|
||||
const [permsId, setPermsId] = useState(null); // v0.5.0: permissions drawer
|
||||
const [perms, setPerms] = useState([]);
|
||||
|
||||
const BASE = window.__BASE__ || '';
|
||||
|
||||
@@ -136,6 +140,46 @@ export default function PackagesSection() {
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
// ── Permissions drawer (v0.5.0) ────────────
|
||||
async function togglePerms(pkgId) {
|
||||
if (permsId === pkgId) { setPermsId(null); setPerms([]); return; }
|
||||
try {
|
||||
const data = await sw.api.admin.packages.permissions(pkgId);
|
||||
setPerms((data && data.data) || data || []);
|
||||
setPermsId(pkgId);
|
||||
// Close settings if open
|
||||
if (expandedId === pkgId) { setExpandedId(null); setPkgSettings(null); }
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function grantPerm(pkgId, perm) {
|
||||
try {
|
||||
await sw.api.admin.packages.grantPerm(pkgId, perm);
|
||||
const data = await sw.api.admin.packages.permissions(pkgId);
|
||||
setPerms((data && data.data) || data || []);
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function revokePerm(pkgId, perm) {
|
||||
try {
|
||||
await sw.api.admin.packages.revokePerm(pkgId, perm);
|
||||
const data = await sw.api.admin.packages.permissions(pkgId);
|
||||
setPerms((data && data.data) || data || []);
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function grantAllPerms(pkgId) {
|
||||
try {
|
||||
await sw.api.admin.packages.grantAllPerms(pkgId);
|
||||
const data = await sw.api.admin.packages.permissions(pkgId);
|
||||
setPerms((data && data.data) || data || []);
|
||||
sw.toast('All permissions granted', 'success');
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
// ── Registry ────────────────────────────────
|
||||
async function toggleRegistry() {
|
||||
if (registryOpen) { setRegistryOpen(false); return; }
|
||||
@@ -166,6 +210,8 @@ export default function PackagesSection() {
|
||||
const dormant = packages.filter(p => p.status === 'dormant').length;
|
||||
const hasManifestSettings = (pkg) =>
|
||||
pkg.manifest?.settings || pkg.package_settings;
|
||||
const hasDeclaredPerms = (pkg) =>
|
||||
pkg.manifest?.permissions && pkg.manifest.permissions.length > 0;
|
||||
|
||||
return html`
|
||||
<div>
|
||||
@@ -211,8 +257,8 @@ export default function PackagesSection() {
|
||||
<div class="admin-actions-cell">
|
||||
<button class="btn-small"
|
||||
onClick=${() => toggleEnabled(pkg)}
|
||||
disabled=${CORE_IDS.has(pkg.id) || pkg.status === 'dormant'}
|
||||
title=${pkg.status === 'dormant' ? 'Requires chat' : ''}>
|
||||
disabled=${CORE_IDS.has(pkg.id) || pkg.status === 'dormant' || pkg.status === 'pending_review'}
|
||||
title=${pkg.status === 'dormant' ? 'Requires chat' : pkg.status === 'pending_review' ? 'Grant permissions to activate' : ''}>
|
||||
${pkg.enabled ? 'Disable' : 'Enable'}
|
||||
</button>
|
||||
${hasManifestSettings(pkg) && html`
|
||||
@@ -220,6 +266,11 @@ export default function PackagesSection() {
|
||||
${expandedId === pkg.id ? 'Close' : 'Settings'}
|
||||
</button>
|
||||
`}
|
||||
${hasDeclaredPerms(pkg) && html`
|
||||
<button class="btn-small" onClick=${() => togglePerms(pkg.id)}>
|
||||
${permsId === pkg.id ? 'Close' : 'Permissions'}
|
||||
</button>
|
||||
`}
|
||||
<button class="btn-small" onClick=${() => exportPkg(pkg.id)}>Export</button>
|
||||
${pkg.source !== 'core' && !pkg.is_system && html`
|
||||
<button class="btn-small btn-danger" onClick=${() => deletePkg(pkg)}>Delete</button>
|
||||
@@ -247,6 +298,35 @@ export default function PackagesSection() {
|
||||
}
|
||||
</div>
|
||||
`}
|
||||
|
||||
${/* ── Inline permissions drawer (v0.5.0) ── */``}
|
||||
${permsId === pkg.id && html`
|
||||
<div style="padding:8px 12px 12px 24px;background:var(--bg-2);border-bottom:1px solid var(--border);">
|
||||
${perms.length === 0
|
||||
? html`<span class="text-muted" style="font-size:12px;">No permissions declared</span>`
|
||||
: html`
|
||||
<div style="margin-bottom:8px;">
|
||||
${perms.map(p => html`
|
||||
<div key=${p.permission} style="display:flex;gap:8px;align-items:center;margin-bottom:4px;">
|
||||
<code style="min-width:140px;font-size:12px;">${p.permission}</code>
|
||||
<button class="btn-small ${p.granted ? 'btn-danger' : 'btn-primary'}"
|
||||
style="min-width:64px;font-size:11px;"
|
||||
onClick=${() => p.granted ? revokePerm(pkg.id, p.permission) : grantPerm(pkg.id, p.permission)}>
|
||||
${p.granted ? 'Revoke' : 'Grant'}
|
||||
</button>
|
||||
${p.granted && p.granted_by && html`
|
||||
<span class="text-muted" style="font-size:11px;">by ${p.granted_by}</span>
|
||||
`}
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
${perms.some(p => !p.granted) && html`
|
||||
<button class="btn-small btn-primary" onClick=${() => grantAllPerms(pkg.id)}>Grant All</button>
|
||||
`}
|
||||
`
|
||||
}
|
||||
</div>
|
||||
`}
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user