Shopfloor PC type system, webapp enhancements, slim Blancco GRUB

- Shopfloor PC type menu (CMM, WaxAndTrace, Keyence, Genspect, Display, Standard)
- Baseline scripts: OpenText CSF, Start Menu shortcuts, network/WinRM, power/display
- Standard type: eDNC + MarkZebra with 64-bit path mirroring
- CMM type: Hexagon CLM Tools, PC-DMIS 2016/2019 R2
- Display sub-type: Lobby vs Dashboard
- Webapp: enrollment management, image config editor, UI refresh
- Upload-Image.ps1: robocopy MCL cache to PXE server
- Download-Drivers.ps1: Dell driver download pipeline
- Slim Blancco GRUB EFI (10MB -> 660KB) for old hardware compat
- Shopfloor display imaging guide docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-03-26 11:25:07 -04:00
parent 6d0e6ee284
commit 76165495ff
49 changed files with 4304 additions and 147 deletions

View File

@@ -150,6 +150,71 @@ document.addEventListener('DOMContentLoaded', function () {
});
}
// -----------------------------------------------------------------------
// Add User Account
// -----------------------------------------------------------------------
var addUserAccountBtn = document.getElementById('addUserAccount');
if (addUserAccountBtn) {
addUserAccountBtn.addEventListener('click', function () {
var tbody = document.querySelector('#userAccountsTable tbody');
var idx = tbody.querySelectorAll('tr').length;
var tr = document.createElement('tr');
tr.innerHTML =
'<td class="order-num">' + (idx + 1) + '</td>' +
'<td><input type="text" class="form-control form-control-sm" name="account_name_' + idx + '" value="" placeholder="Username"></td>' +
'<td><input type="text" class="form-control form-control-sm" name="account_password_' + idx + '" value="" placeholder="Password"></td>' +
'<td><input type="text" class="form-control form-control-sm" name="account_group_' + idx + '" value="Administrators"></td>' +
'<td><input type="text" class="form-control form-control-sm" name="account_display_' + idx + '" value="" placeholder="Display Name"></td>' +
'<td>' +
'<input type="hidden" name="account_plaintext_' + idx + '" value="true">' +
'<button type="button" class="btn btn-outline-danger btn-row-action remove-account-row">Remove</button>' +
'</td>';
tbody.appendChild(tr);
var emptyEl = document.getElementById('userAccountsEmpty');
if (emptyEl) emptyEl.style.display = 'none';
tr.querySelector('input[name^="account_name_"]').focus();
});
}
// -----------------------------------------------------------------------
// Remove User Account row + renumber indices (delegated)
// -----------------------------------------------------------------------
document.addEventListener('click', function (e) {
var btn = e.target.closest('.remove-account-row');
if (!btn) return;
var row = btn.closest('tr');
var tbody = row.parentElement;
row.remove();
// Renumber order and field name indices
var rows = tbody.querySelectorAll('tr');
rows.forEach(function (r, i) {
var orderCell = r.querySelector('.order-num');
if (orderCell) orderCell.textContent = i + 1;
// Rename inputs to match new index
r.querySelectorAll('input').forEach(function (inp) {
var name = inp.getAttribute('name');
if (name) {
inp.setAttribute('name', name.replace(/_\d+$/, '_' + i));
}
});
});
var emptyEl = document.getElementById('userAccountsEmpty');
if (emptyEl) emptyEl.style.display = rows.length > 0 ? 'none' : '';
});
// -----------------------------------------------------------------------
// AutoLogon Enabled toggle — keep hidden input in sync
// -----------------------------------------------------------------------
var autologonToggle = document.getElementById('autologonEnabledToggle');
if (autologonToggle) {
autologonToggle.addEventListener('change', function () {
var hidden = document.getElementById('autologon_enabled_val');
if (hidden) {
hidden.value = this.checked ? 'true' : 'false';
}
});
}
// -----------------------------------------------------------------------
// OOBE toggle switches — keep hidden input in sync
// -----------------------------------------------------------------------
@@ -298,5 +363,107 @@ document.addEventListener('DOMContentLoaded', function () {
toggleEmpty('driverPathsTable', 'driverPathsEmpty');
toggleEmpty('specCmdTable', 'specCmdEmpty');
toggleEmpty('flCmdTable', 'flCmdEmpty');
toggleEmpty('userAccountsTable', 'userAccountsEmpty');
// =======================================================================
// Image Configuration Editor handlers
// =======================================================================
// -----------------------------------------------------------------------
// Generic: collect table rows into JSON and submit form
// -----------------------------------------------------------------------
function collectAndSubmit(tableId, hiddenId, formId, extractor) {
var tbody = document.querySelector('#' + tableId + ' tbody');
if (!tbody) return;
var rows = tbody.querySelectorAll('tr');
var data = [];
rows.forEach(function (row) {
var item = extractor(row);
if (item) data.push(item);
});
document.getElementById(hiddenId).value = JSON.stringify(data);
document.getElementById(formId).submit();
}
// Helper: extract JSON from data-json attr, stripping internal _fields
function extractDataJson(row) {
var raw = row.getAttribute('data-json');
if (!raw) return null;
try {
var obj = JSON.parse(raw);
Object.keys(obj).forEach(function (k) {
if (k.charAt(0) === '_') delete obj[k];
});
return obj;
} catch (e) { return null; }
}
// -----------------------------------------------------------------------
// Save: Hardware Models
// -----------------------------------------------------------------------
var saveHwModelsBtn = document.getElementById('saveHwModels');
if (saveHwModelsBtn) {
saveHwModelsBtn.addEventListener('click', function () {
collectAndSubmit('hwModelsTable', 'hwModelsData', 'hwModelsForm', function (row) {
var m = row.querySelector('[data-field="Model"]');
var f = row.querySelector('[data-field="Id"]');
if (!m || !f) return null;
return { Model: m.value, Id: f.value };
});
});
}
// -----------------------------------------------------------------------
// Save: Drivers
// -----------------------------------------------------------------------
var saveDriversBtn = document.getElementById('saveDrivers');
if (saveDriversBtn) {
saveDriversBtn.addEventListener('click', function () {
collectAndSubmit('driversTable', 'driversData', 'driversForm', extractDataJson);
});
}
// -----------------------------------------------------------------------
// Save: Operating Systems
// -----------------------------------------------------------------------
var saveOsBtn = document.getElementById('saveOs');
if (saveOsBtn) {
saveOsBtn.addEventListener('click', function () {
collectAndSubmit('osTable', 'osData', 'osForm', extractDataJson);
});
}
// -----------------------------------------------------------------------
// Save: Packages
// -----------------------------------------------------------------------
var savePackagesBtn = document.getElementById('savePackages');
if (savePackagesBtn) {
savePackagesBtn.addEventListener('click', function () {
collectAndSubmit('packagesTable', 'packagesData', 'packagesForm', extractDataJson);
});
}
// -----------------------------------------------------------------------
// Add Hardware Model row
// -----------------------------------------------------------------------
var addHwModelBtn = document.getElementById('addHwModel');
if (addHwModelBtn) {
addHwModelBtn.addEventListener('click', function () {
var tbody = document.querySelector('#hwModelsTable tbody');
var idx = tbody.querySelectorAll('tr').length + 1;
var tr = document.createElement('tr');
tr.innerHTML =
'<td class="order-num">' + idx + '</td>' +
'<td><input type="text" class="form-control form-control-sm" data-field="Model" value="" placeholder="Model name"></td>' +
'<td><input type="text" class="form-control form-control-sm" data-field="Id" value="" placeholder="Driver Family ID"></td>' +
'<td><span class="badge bg-secondary badge-disk">New</span></td>' +
'<td><button type="button" class="btn btn-outline-danger btn-row-action remove-row"><i class="bi bi-trash"></i></button></td>';
tbody.appendChild(tr);
var empty = document.getElementById('hwModelsEmpty');
if (empty) empty.style.display = 'none';
tr.querySelector('input').focus();
});
}
});