diff --git a/plugins/ms-ai-architect/playground/ms-ai-architect-v3.html b/plugins/ms-ai-architect/playground/ms-ai-architect-v3.html index 7f70b13..660ad56 100644 --- a/plugins/ms-ai-architect/playground/ms-ai-architect-v3.html +++ b/plugins/ms-ai-architect/playground/ms-ai-architect-v3.html @@ -1440,7 +1440,7 @@ if (active === 'onboarding') renderOnboardingSurface(); else if (active === 'home') renderHomeSurface(); else if (active === 'project') renderProjectSurface(); - else if (active === 'catalog') renderCatalogStub(); + else if (active === 'catalog') renderCatalogSurface(); } function navigate(surface) { @@ -1920,10 +1920,164 @@ ); } - function renderCatalogStub() { + // ============================================================ + // CATALOG SURFACE (Step 9) + // ============================================================ + // + // 24 commands gruppert i 5 .expansion-grupper (CATALOG.categories) med + // søke-input som filtrerer på id+label+description+argument_hint. + // Hver kategori-expansion rendrer en .catalog-cards-grid med kort. + // "Åpne skjema" på et kort åpner renderCommandForm() i modal. + // + // Søk: input-event oppdaterer modul-lokal catalogSearchQuery og + // re-rendrer kun groups-containeren (bevarer fokus/cursor i søkefeltet). + // Når query er ikke-tom forces alle expansions åpne. I tom-state er + // 'regulatory' åpen som standard (mest brukt entry-point). + // + // Verktøy-commands får .catalog-tool-notice "Verktøy"-pill + samme + // skjema-modal — ingen rapport-import (parser/renderer hopper dem over). + + let catalogSearchQuery = ''; + + function catalogMatches(cmd, q) { + if (!q) return true; + const hay = ( + (cmd.id || '') + ' ' + + (cmd.label || '') + ' ' + + (cmd.description || '') + ' ' + + (cmd.argument_hint || '') + ).toLowerCase(); + return hay.indexOf(q) >= 0; + } + + function renderCatalogCardHtml(cmd) { + const isVerktoy = !cmd.produces_report; + const pill = isVerktoy + ? 'Verktøy' + : 'Rapport'; + const hintHtml = cmd.argument_hint + ? '' + escapeHtml(cmd.argument_hint) + '' + : ''; + const verktoyNotice = isVerktoy + ? '
Verktøy — ingen rapport-import. Skjema bygger pipeline-streng som kjøres i terminalen.
' + : ''; + return ( + '
' + + '
' + + '
' + + '

' + escapeHtml(cmd.label) + '

' + + '

' + escapeHtml(cmd.description) + '

' + + '
' + + pill + + '
' + + '
' + + '/architect:' + escapeHtml(cmd.id) + '' + + hintHtml + + '
' + + verktoyNotice + + '
' + + '' + + '
' + + '
' + ); + } + + function renderCatalogGroupsHtml() { + const q = (catalogSearchQuery || '').trim().toLowerCase(); + return CATALOG.categories.map(function (cat) { + const cmds = CATALOG.commands.filter(function (c) { + return c.category === cat.id && catalogMatches(c, q); + }); + const cardsHtml = cmds.map(renderCatalogCardHtml).join(''); + // Force-open når aktiv søk-query har treff. Ellers: 'regulatory' åpen som default. + const expanded = q ? (cmds.length > 0 ? 'true' : 'false') : (cat.id === 'regulatory' ? 'true' : 'false'); + const subLabel = cmds.length === cat.count + ? cat.count + ' commands' + : cmds.length + ' / ' + cat.count + ' commands'; + const body = cmds.length > 0 + ? '
' + cardsHtml + '
' + : '

Ingen treff i denne kategorien.

'; + return ( + '
' + + '' + + '
' + + '
' + body + '
' + + '
' + + '
' + ); + }).join(''); + } + + function renderCatalogSurface() { const root = getSurfaceEl('catalog'); if (!root) return; - root.innerHTML = renderTopbar('Katalog') + '

Command-katalog fylles i Step 9.

'; + const q = (catalogSearchQuery || '').trim().toLowerCase(); + const totalMatches = CATALOG.commands.filter(function (c) { return catalogMatches(c, q); }).length; + const countText = totalMatches + ' av ' + CATALOG.commands.length + ' treff' + (q ? ' for «' + escapeHtml(catalogSearchQuery) + '»' : ''); + root.innerHTML = ( + renderTopbar('Katalog') + + '
' + + '
' + + '

Command-katalog

' + + '

24 commands gruppert i 5 kategorier. Åpne skjema for å bygge en pipeline-streng som kopieres til terminalen og kjøres med Claude Code.

' + + '
' + + '
' + + '' + + '' + countText + '' + + '
' + + '
' + renderCatalogGroupsHtml() + '
' + + '
' + ); + } + + function refreshCatalogResults() { + const root = getSurfaceEl('catalog'); + if (!root) return; + const groupsEl = root.querySelector('[data-catalog-groups]'); + if (groupsEl) groupsEl.innerHTML = renderCatalogGroupsHtml(); + const countEl = root.querySelector('[data-catalog-count]'); + if (countEl) { + const q = (catalogSearchQuery || '').trim().toLowerCase(); + const totalMatches = CATALOG.commands.filter(function (c) { return catalogMatches(c, q); }).length; + countEl.textContent = totalMatches + ' av ' + CATALOG.commands.length + ' treff' + (q ? ' for «' + catalogSearchQuery + '»' : ''); + } + } + + function renderCatalogFormModalHtml(cmd) { + const formHtml = renderCommandForm(cmd.id, { context: 'modal', scope: 'm' }); + const verktoyBanner = !cmd.produces_report + ? ( + '
' + + '' + + '
' + + '

Verktøy

' + + '

Dette er et verktøy. Skjemaet bygger en pipeline-streng — ingen rapport-import.

' + + '
' + + '
' + ) + : ''; + return ( + '' + ); } // ---- Paste-import stub (Step 12 erstatter med faktisk routing) ---- @@ -2457,6 +2611,31 @@ showCommandPreview(formEl, buildCommand(commandId, data)); }; + // ---- Step 9: catalog actions ---- + + ACTIONS['open-catalog-form'] = function (ev, el) { + const commandId = el.dataset.command; + if (!commandId) return; + const cmd = (CATALOG.commands || []).find(function (c) { return c.id === commandId; }); + if (!cmd) return; + mountModal(renderCatalogFormModalHtml(cmd)); + }; + + ACTIONS['catalog-toggle-group'] = function (ev, el) { + const exp = el.closest('.expansion'); + if (!exp) return; + const open = exp.getAttribute('aria-expanded') === 'true'; + exp.setAttribute('aria-expanded', open ? 'false' : 'true'); + }; + + // Søk-input: input-event oppdaterer query og re-rendrer kun groups-containeren + // (bevarer fokus/cursor i selve søke-feltet — full re-render ville flyttet caret). + document.addEventListener('input', function (ev) { + if (!ev.target.matches || !ev.target.matches('[data-catalog-search]')) return; + catalogSearchQuery = ev.target.value || ''; + refreshCatalogResults(); + }); + // Eksponer for Verify-asserts og Step 8/9/12. window.__SCENARIOS = SCENARIOS; window.__createProject = createProject; @@ -2468,6 +2647,8 @@ window.__renderCommandForm = renderCommandForm; window.__readCommandFormValues = readCommandFormValues; window.__resolveSharedPath = resolveSharedPath; + window.__renderCatalogSurface = renderCatalogSurface; + window.__refreshCatalogResults = refreshCatalogResults; ACTIONS['export-state'] = function () { try { exportState(); }