Setup wizard: plugin display names + GE-Enforce next-steps pointer
Plugins list now carries a displayname (manifest display_name, else the machine name title-cased). Adds display_name to the four whose title-case was wrong: GE-Enforce, USB, Measuring Tools, Knowledge Base. The setup wizard Features step and Settings > Plugins render it, so "Geenforce"/"Usb" are gone. Finish step shows a pointer when GE-Enforce is enabled: it still needs a scoped service token (Settings > API Tokens) and a share export root (GE-Enforce page) before the fleet uses it - operational config the wizard does not collect. frontend build green; naming green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,7 @@
|
|||||||
<div v-for="p in plugins" :key="p.name" class="plugin-item">
|
<div v-for="p in plugins" :key="p.name" class="plugin-item">
|
||||||
<label class="plugin-row">
|
<label class="plugin-row">
|
||||||
<input type="checkbox" :checked="p.enabled" @change="togglePlugin(p, $event.target.checked)" />
|
<input type="checkbox" :checked="p.enabled" @change="togglePlugin(p, $event.target.checked)" />
|
||||||
<span class="plugin-name">{{ p.name }}</span>
|
<span class="plugin-name">{{ p.displayname || p.name }}</span>
|
||||||
<span class="plugin-desc">{{ p.description }}</span>
|
<span class="plugin-desc">{{ p.description }}</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
@@ -140,6 +140,12 @@
|
|||||||
<div v-else-if="current.key === 'finish'">
|
<div v-else-if="current.key === 'finish'">
|
||||||
<h2>All set</h2>
|
<h2>All set</h2>
|
||||||
<p class="hint">You can change any of this later under Settings. Finish to go to the dashboard.</p>
|
<p class="hint">You can change any of this later under Settings. Finish to go to the dashboard.</p>
|
||||||
|
<div v-if="geenforceEnabled" class="finish-note">
|
||||||
|
<strong>GE-Enforce is on.</strong> Two more steps before the fleet
|
||||||
|
uses it: create a service token with the geenforce scopes under
|
||||||
|
Settings > API Tokens, and set the on-share export root on the
|
||||||
|
GE-Enforce page.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -235,6 +241,11 @@ function modeOf(plugin) {
|
|||||||
return key ? (pluginModes.value[key] || 'selfhosted') : null
|
return key ? (pluginModes.value[key] || 'selfhosted') : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GE-Enforce needs post-setup operational config (service token + share root)
|
||||||
|
// the wizard does not collect; the Finish step points there when it is on.
|
||||||
|
const geenforceEnabled = computed(() =>
|
||||||
|
plugins.value.some(p => p.name === 'geenforce' && p.enabled))
|
||||||
|
|
||||||
// Enabled plugins whose external connection config should be collected right
|
// Enabled plugins whose external connection config should be collected right
|
||||||
// now: those in external mode (or with config but no mode concept).
|
// now: those in external mode (or with config but no mode concept).
|
||||||
const configurablePlugins = computed(() =>
|
const configurablePlugins = computed(() =>
|
||||||
@@ -420,13 +431,14 @@ async function finish() {
|
|||||||
.form-row .form-group { flex: 1; }
|
.form-row .form-group { flex: 1; }
|
||||||
.plugin-list { display: flex; flex-direction: column; gap: 0.6rem; }
|
.plugin-list { display: flex; flex-direction: column; gap: 0.6rem; }
|
||||||
.plugin-row { display: grid; grid-template-columns: auto auto 1fr; gap: 0.6rem; align-items: baseline; padding: 0.5rem 0.6rem; background: var(--bg); border-radius: 6px; }
|
.plugin-row { display: grid; grid-template-columns: auto auto 1fr; gap: 0.6rem; align-items: baseline; padding: 0.5rem 0.6rem; background: var(--bg); border-radius: 6px; }
|
||||||
.plugin-name { font-weight: 600; text-transform: capitalize; }
|
.plugin-name { font-weight: 600; }
|
||||||
.plugin-desc { color: var(--text-light); font-size: 0.85rem; }
|
.plugin-desc { color: var(--text-light); font-size: 0.85rem; }
|
||||||
.plugin-mode { margin: 0.4rem 0 0.2rem 1.9rem; }
|
.plugin-mode { margin: 0.4rem 0 0.2rem 1.9rem; }
|
||||||
.mode-opt { display: block; font-size: 0.86rem; margin-bottom: 0.3rem; cursor: pointer; }
|
.mode-opt { display: block; font-size: 0.86rem; margin-bottom: 0.3rem; cursor: pointer; }
|
||||||
.mode-opt input { margin-right: 0.4rem; }
|
.mode-opt input { margin-right: 0.4rem; }
|
||||||
.plugin-mode .provision-note, .plugin-mode .config-block { margin-left: 0; }
|
.plugin-mode .provision-note, .plugin-mode .config-block { margin-left: 0; }
|
||||||
.provision-note { margin: 0.3rem 0 0.2rem 1.9rem; padding: 0.6rem 0.75rem; background: var(--bg); border-left: 3px solid var(--warning); border-radius: 4px; font-size: 0.82rem; }
|
.provision-note { margin: 0.3rem 0 0.2rem 1.9rem; padding: 0.6rem 0.75rem; background: var(--bg); border-left: 3px solid var(--warning); border-radius: 4px; font-size: 0.82rem; }
|
||||||
|
.finish-note { margin: 0.75rem 0 0; padding: 0.6rem 0.75rem; background: var(--bg); border-left: 3px solid var(--primary); border-radius: 4px; font-size: 0.85rem; }
|
||||||
.provision-note p { margin: 0 0 0.35rem; }
|
.provision-note p { margin: 0 0 0.35rem; }
|
||||||
.provision-note p:last-child { margin-bottom: 0; }
|
.provision-note p:last-child { margin-bottom: 0; }
|
||||||
.provision-tables code, .provision-docs code { background: var(--bg-card); border: 1px solid var(--border); border-radius: 3px; padding: 0 0.3rem; margin-right: 0.3rem; font-size: 0.78rem; }
|
.provision-tables code, .provision-docs code { background: var(--bg-card); border: 1px solid var(--border); border-radius: 3px; padding: 0 0.3rem; margin-right: 0.3rem; font-size: 0.78rem; }
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="p in plugins" :key="p.name">
|
<tr v-for="p in plugins" :key="p.name">
|
||||||
<td>{{ p.name }}</td>
|
<td>{{ p.displayname || p.name }}</td>
|
||||||
<td class="mono">{{ p.version }}</td>
|
<td class="mono">{{ p.version }}</td>
|
||||||
<td class="cell-truncate" :title="p.description">{{ p.description || '-' }}</td>
|
<td class="cell-truncate" :title="p.description">{{ p.description || '-' }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "geenforce",
|
"name": "geenforce",
|
||||||
|
"display_name": "GE-Enforce",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "GE-Enforce manifest store. Owns imaging PC-type scopes and their install manifests (apps, scripts, files, registry, version gates) as shopdb data, served to the GE-Enforce client as JSON. Requires GE-Enforce lib >= 2.6 on target PCs (the _CmmVersion gate).",
|
"description": "GE-Enforce manifest store. Owns imaging PC-type scopes and their install manifests (apps, scripts, files, registry, version gates) as shopdb data, served to the GE-Enforce client as JSON. Requires GE-Enforce lib >= 2.6 on target PCs (the _CmmVersion gate).",
|
||||||
"author": "ShopDB Team",
|
"author": "ShopDB Team",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "knowledgebase",
|
"name": "knowledgebase",
|
||||||
|
"display_name": "Knowledge Base",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Knowledge Base articles linking to external resources",
|
"description": "Knowledge Base articles linking to external resources",
|
||||||
"author": "ShopDB Team",
|
"author": "ShopDB Team",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "measuringtools",
|
"name": "measuringtools",
|
||||||
|
"display_name": "Measuring Tools",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Metrology and inspection instruments (gauges, calipers, thread gages, bore gages) with a calibration lifecycle and derived calibration status.",
|
"description": "Metrology and inspection instruments (gauges, calipers, thread gages, bore gages) with a calibration lifecycle and derived calibration status.",
|
||||||
"author": "ShopDB Team",
|
"author": "ShopDB Team",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "usb",
|
"name": "usb",
|
||||||
|
"display_name": "USB",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "USB device checkout management",
|
"description": "USB device checkout management",
|
||||||
"author": "ShopDB Team",
|
"author": "ShopDB Team",
|
||||||
|
|||||||
@@ -155,6 +155,11 @@ class PluginManager:
|
|||||||
manifest = self.loader.load_manifest(name)
|
manifest = self.loader.load_manifest(name)
|
||||||
available.append({
|
available.append({
|
||||||
'name': meta.name,
|
'name': meta.name,
|
||||||
|
# Human label for UIs. Manifest display_name wins; else
|
||||||
|
# title-case the machine name (right for most, e.g.
|
||||||
|
# "computers" -> "Computers").
|
||||||
|
'displayname': (manifest.get('display_name')
|
||||||
|
or meta.name.replace('_', ' ').title()),
|
||||||
'version': meta.version,
|
'version': meta.version,
|
||||||
'description': meta.description,
|
'description': meta.description,
|
||||||
'author': meta.author,
|
'author': meta.author,
|
||||||
|
|||||||
Reference in New Issue
Block a user