Feat v0.2.3 sdk tasks (#7)
Some checks failed
CI/CD / detect-changes (push) Successful in 23s
CI/CD / test-frontend (push) Successful in 5s
CI/CD / test-go-pg (push) Failing after 2m27s
CI/CD / test-sqlite (push) Successful in 2m34s
CI/CD / build-and-deploy (push) Has been skipped

Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #7.
This commit is contained in:
2026-03-27 11:06:40 +00:00
committed by xcaliber
parent 57ccf19efb
commit 239a5fb732
26 changed files with 2230 additions and 38 deletions

View File

@@ -34,13 +34,15 @@ export function UserMenu({ placement = 'down-right', onAction, extraItems }) {
const user = sw?.auth?.user;
const authenticated = sw?.auth?.isAuthenticated;
// Fetch extension surfaces once on mount
// Fetch installed surfaces once on mount.
// Filter out core surfaces that have dedicated menu entries below.
const CORE_IDS = new Set(['admin', 'settings', 'team-admin', 'workflow', 'workflow-landing']);
useEffect(() => {
if (!sw?.api?.surfaces?.list) return;
sw.api.surfaces.list().then(data => {
const all = data || [];
const CORE = new Set(['chat', 'admin', 'notes', 'settings', 'team-admin', 'projects', 'workflow', 'workflow-landing']);
setExtSurfaces(all.filter(s => !CORE.has(s.id)));
const raw = Array.isArray(data) ? data : data?.data || [];
setExtSurfaces(raw.filter(s => !CORE_IDS.has(s.id)));
}).catch(() => {});
}, [authenticated]);
@@ -48,22 +50,11 @@ export function UserMenu({ placement = 'down-right', onAction, extraItems }) {
const current = _currentSurface();
const list = [];
// ── Surface links (auto-filtered) ──────
// Each surface that exists gets a menu item, except the current one.
const surfaces = [
{ key: 'chat', label: 'Chat', icon: '\ud83d\udcac' },
{ key: 'notes', label: 'Notes', icon: '\ud83d\udcdd' },
{ key: 'projects', label: 'Projects', icon: '\ud83d\udcc1' },
];
// Add extension surfaces fetched from API
for (const ext of extSurfaces) {
surfaces.push({ key: ext.id, label: ext.title, icon: '\ud83e\udde9', route: ext.route });
}
const surfaceItems = surfaces
.filter(s => s.key !== current)
.map(s => ({ label: s.label, action: s.key, icon: s.icon }));
// ── Surface links (from API — only installed surfaces) ──────
const DEFAULT_ICON = '\ud83e\udde9';
const surfaceItems = extSurfaces
.filter(s => s.id !== current)
.map(s => ({ label: s.title, action: s.id, icon: s.icon || DEFAULT_ICON }));
if (surfaceItems.length) {
list.push(...surfaceItems);
@@ -119,11 +110,8 @@ export function UserMenu({ placement = 'down-right', onAction, extraItems }) {
case 'debug':
window.dispatchEvent(new CustomEvent('debug:toggle'));
break;
case 'chat':
location.href = BASE + '/';
break;
default: {
// Extension surfaces use /s/{id} routes
// Surfaces use their route from the API, or fall back to /{id}
const ext = extSurfaces.find(s => s.id === action);
location.href = BASE + (ext?.route || '/' + action);
break;