diff --git a/frontend/src/views/geenforce/ManifestEditor.vue b/frontend/src/views/geenforce/ManifestEditor.vue index 8a52704..1b8c72c 100644 --- a/frontend/src/views/geenforce/ManifestEditor.vue +++ b/frontend/src/views/geenforce/ManifestEditor.vue @@ -89,6 +89,7 @@ +

{{ scopeSummary }}

@@ -330,8 +330,9 @@ Detection method + Preinstall supports Registry/File detection only.
@@ -430,8 +431,8 @@
-
- Preinstall flags (preinstall phase only): +
+ Preinstall flags (only take effect at imaging): @@ -494,6 +495,38 @@ const error = ref('') const notice = ref('') const shareRoot = ref('') +// Phase-aware editing: the PREINSTALL runner implements only MSI/EXE types and +// Registry/File detection (other types/detections are silently skipped there), +// and only preinstall honors the preinstall flags. Restrict the form for a +// preinstall scope so an author cannot pick an option that would do nothing. +const isPreinstallScope = computed(() => detail.value?.phase === 'preinstall') +const availableEntryTypes = computed(() => { + if (!isPreinstallScope.value) return ENTRY_TYPES + const allowed = ['MSI', 'EXE'] + // keep the current value visible even if it is out of the allowed set + const current = entryForm.value?.Type + return current && !allowed.includes(current) ? [...allowed, current] : allowed +}) +const availableDetectionMethods = computed(() => { + if (!isPreinstallScope.value) return DETECTION_METHODS + const allowed = ['Registry', 'File'] + const current = entryForm.value?.DetectionMethod + return current && !allowed.includes(current) ? [...allowed, current] : allowed +}) + +// One-line summary of what a scope installs (installer entries only). +const scopeSummary = computed(() => { + const scope = detail.value + if (!scope || !scope.entries || !scope.entries.length) return '' + const installers = scope.entries + .filter(e => ['MSI', 'EXE', 'CMD', 'BAT'].includes(e.Type)) + .map(e => e.Name) + const shown = installers.slice(0, 6).join(', ') + const more = installers.length > 6 ? `, +${installers.length - 6} more` : '' + const apps = installers.length ? `Installs ${shown}${more}. ` : '' + return `${apps}${scope.entries.length} entries; runs after common.` +}) + // Show only the targeting gates a scope actually uses (a per-type manifest // already runs on its own type, so PCTypes is noise there; CMM shows a version // gate; collections shows machine numbers; the common/preinstall manifests use @@ -892,7 +925,18 @@ loadConfig() /* Modals: wider entry/preview, still responsive (global max-width + width:100%). */ .modal-entry { max-width: min(1100px, 96vw); } .toggle-all { font-weight: 400; font-size: 0.8rem; } -.entry-desc { font-size: 0.78rem; margin-top: 0.15rem; } +.entry-name { font-weight: 500; } +.entry-desc { font-size: 0.78rem; margin-top: 0.15rem; overflow-wrap: anywhere; } +.scope-summary { margin: 0 0 0.75rem 0; font-size: 0.85rem; } +/* Fixed layout so the Entry column flexes and the button columns never force + a horizontal scroll. */ +.scope-detail .entries-table { width: 100%; table-layout: fixed; } +.entries-table th.col-order, .entries-table td.order-cell { width: 58px; } +.entries-table th.col-type { width: 64px; } +.entries-table th.col-actions, .entries-table td.row-actions { width: 128px; } +.order-cell { display: flex; flex-direction: column; gap: 0.2rem; } +.order-cell .btn { padding: 0.1rem 0.3rem; } +.row-actions { display: flex; gap: 0.3rem; flex-wrap: wrap; } .help-panel { margin: 0 0 1rem 0; border: 1px solid var(--border); border-radius: 6px; padding: 0.5rem 0.75rem; background: var(--bg-card); } .help-panel summary { cursor: pointer; font-weight: 600; font-size: 0.9rem; }