Make GE-Enforce editor more legible: plain-English entries + how-it-works panel
- Each manifest entry now shows a one-line intent summary under its name (e.g. 'Installs eDNC; reinstalls if not detected; 2 PC types') instead of only the raw Type/Detection/Filters columns - turns jargon into what it actually does. - A collapsible 'How this works' panel at the top gives the mental model in four sentences (desired state + self-heal, entries + detection, targeting, doc link). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,25 @@
|
||||
then Publish to ship it to PCs. Nothing reaches a PC until you publish.
|
||||
</p>
|
||||
|
||||
<details class="help-panel">
|
||||
<summary>How this works</summary>
|
||||
<div class="help-body">
|
||||
<p><strong>A manifest is the desired state for a PC type</strong> - the
|
||||
list of what should be installed. shopdb serves it; each PC checks
|
||||
itself every cycle and re-installs anything that drifted (uninstalled,
|
||||
corrupted, or overwritten). That is the "self-heal".</p>
|
||||
<p><strong>Each entry</strong> is one action (install an app, copy a
|
||||
file, write a registry value, run a script) plus a <em>detection</em>
|
||||
rule that tells the PC whether it is already correct - if not, the
|
||||
action runs. Entry order is execution order.</p>
|
||||
<p><strong>Targeting</strong> narrows an entry: the fleet-wide
|
||||
<code>common</code> manifest uses PC types to hit a subset; a per-type
|
||||
manifest already only runs on its own type, so it shows just the niche
|
||||
gate it needs (CMM version, a bay number, a subtype).</p>
|
||||
<p>Full guide: <code>docs/GE-ENFORCE.md</code>.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div v-if="error" class="error-message">{{ error }}</div>
|
||||
<div v-if="notice" class="settings-success">{{ notice }}</div>
|
||||
|
||||
@@ -151,7 +170,10 @@
|
||||
@click="moveEntry(index, 1)"
|
||||
>Down</button>
|
||||
</td>
|
||||
<td>{{ entry.Name }}</td>
|
||||
<td>
|
||||
{{ entry.Name }}
|
||||
<div class="entry-desc muted">{{ describeEntry(entry) }}</div>
|
||||
</td>
|
||||
<td><span class="badge badge-info">{{ entry.Type }}</span></td>
|
||||
<td class="muted">{{ entry.DetectionMethod || 'always' }}</td>
|
||||
<td class="muted">{{ filterSummary(entry) }}</td>
|
||||
@@ -749,6 +771,32 @@ function filterSummary(entry) {
|
||||
if (entry._CmmVersion) parts.push(`cmm:${entry._CmmVersion}`)
|
||||
return parts.join(' ') || '-'
|
||||
}
|
||||
|
||||
// Plain-English one-liner: what this entry does, when it self-heals, who it
|
||||
// applies to. Turns "eDNC | MSI | Registry | -" into intent an IT tech reads.
|
||||
const ACTION_VERB = {
|
||||
MSI: 'Installs', EXE: 'Installs', CMD: 'Runs', BAT: 'Runs',
|
||||
PS1: 'Runs a script for', INF: 'Installs a driver for',
|
||||
File: 'Copies a file for', Registry: 'Sets a registry value for',
|
||||
}
|
||||
function describeEntry(entry) {
|
||||
let text = `${ACTION_VERB[entry.Type] || 'Applies'} ${entry.Name}`
|
||||
const method = entry.DetectionMethod
|
||||
if (!method || method === 'Always') text += '; runs every cycle'
|
||||
else if (method === 'FileVersion') text += `; reinstalls unless version is ${entry.DetectionValue || 'set'}`
|
||||
else if (method === 'Hash') text += '; re-copies if the file changed'
|
||||
else if (method === 'MarkerFile') text += '; installs once'
|
||||
else text += '; reinstalls if not detected'
|
||||
if (entry._CmmVersion) text += `; CMM ${entry._CmmVersion} bays only`
|
||||
else if (entry.TargetMachineNumbers && entry.TargetMachineNumbers.length) {
|
||||
text += `; ${entry.TargetMachineNumbers.length} specific bay(s)`
|
||||
} else if (entry.TargetHostnames && entry.TargetHostnames.length) {
|
||||
text += '; specific hostname(s)'
|
||||
} else if (entry.PCTypes && entry.PCTypes.length) {
|
||||
text += `; ${entry.PCTypes.length} PC type(s)`
|
||||
}
|
||||
return text
|
||||
}
|
||||
function formatDate(value) {
|
||||
return value ? new Date(value).toLocaleString() : ''
|
||||
}
|
||||
@@ -844,6 +892,13 @@ 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; }
|
||||
.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; }
|
||||
.help-body { margin-top: 0.5rem; }
|
||||
.help-body p { margin: 0 0 0.5rem 0; font-size: 0.85rem; color: var(--text-light); }
|
||||
.help-body code { font-size: 0.8rem; }
|
||||
.modal-close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
|
||||
Reference in New Issue
Block a user