Give the pages one switch and one prefix each
Three pages had reimplemented the same sliding toggle, and two both claimed vv-set-* with disjoint class names, which reads as shared and is not.
This commit is contained in:
@@ -72,26 +72,26 @@
|
||||
}
|
||||
|
||||
/* ── Settings panel ─────────────────────────────────────────── */
|
||||
.vv-set-file { border:1px solid #222; border-radius:5px; margin-bottom:8px; overflow:hidden; }
|
||||
.vv-set-file-hdr { display:flex; justify-content:space-between; align-items:center; padding:8px 12px;
|
||||
.vv-pt-set-file { border:1px solid #222; border-radius:5px; margin-bottom:8px; overflow:hidden; }
|
||||
.vv-pt-set-file-hdr { display:flex; justify-content:space-between; align-items:center; padding:8px 12px;
|
||||
background:#161616; cursor:pointer; font-size:12px; font-weight:bold; color:#bbb; font-family:monospace; }
|
||||
.vv-set-file-hdr:hover { background:#1a1a1a; }
|
||||
.vv-set-file-body { padding:6px 10px 10px; }
|
||||
.vv-set-sec { border-top:1px solid #1c1c1c; }
|
||||
.vv-set-sec:first-child { border-top:none; }
|
||||
.vv-set-sec-hdr { display:flex; justify-content:space-between; align-items:center; padding:6px 4px;
|
||||
.vv-pt-set-file-hdr:hover { background:#1a1a1a; }
|
||||
.vv-pt-set-file-body { padding:6px 10px 10px; }
|
||||
.vv-pt-set-sec { border-top:1px solid #1c1c1c; }
|
||||
.vv-pt-set-sec:first-child { border-top:none; }
|
||||
.vv-pt-set-sec-hdr { display:flex; justify-content:space-between; align-items:center; padding:6px 4px;
|
||||
cursor:pointer; font-size:11px; color:#888; text-transform:uppercase; letter-spacing:.04em; }
|
||||
.vv-set-sec-hdr:hover { color:#ccc; }
|
||||
.vv-set-sec-body { padding:4px 0 8px 8px; }
|
||||
.vv-set-chev { color:#444; font-size:10px; }
|
||||
.vv-set-field { margin-bottom:10px; }
|
||||
.vv-set-key { font-size:11px; color:#7ab; font-family:monospace; margin-bottom:2px; }
|
||||
.vv-set-desc { font-size:10px; color:#555; margin-bottom:3px; line-height:1.4; }
|
||||
.vv-set-input { width:100%; box-sizing:border-box; background:#0d0d0d; border:1px solid #2a2a2a;
|
||||
.vv-pt-set-sec-hdr:hover { color:#ccc; }
|
||||
.vv-pt-set-sec-body { padding:4px 0 8px 8px; }
|
||||
.vv-pt-set-chev { color:#444; font-size:10px; }
|
||||
.vv-pt-set-field { margin-bottom:10px; }
|
||||
.vv-pt-set-key { font-size:11px; color:#7ab; font-family:monospace; margin-bottom:2px; }
|
||||
.vv-pt-set-desc { font-size:10px; color:#555; margin-bottom:3px; line-height:1.4; }
|
||||
.vv-pt-set-input { width:100%; box-sizing:border-box; background:#0d0d0d; border:1px solid #2a2a2a;
|
||||
color:#ddd; padding:5px 8px; border-radius:3px; font-family:monospace; font-size:11px; }
|
||||
.vv-set-input:focus { outline:none; border-color:#4a8; }
|
||||
.vv-set-input.changed { border-color:#ff9800; }
|
||||
textarea.vv-set-input { resize:vertical; white-space:pre; }
|
||||
.vv-pt-set-input:focus { outline:none; border-color:#4a8; }
|
||||
.vv-pt-set-input.changed { border-color:#ff9800; }
|
||||
textarea.vv-pt-set-input { resize:vertical; white-space:pre; }
|
||||
</style>
|
||||
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 2px;">
|
||||
@@ -361,9 +361,9 @@ function _renderHostSettings(nodes, isOwner) {
|
||||
for (const n of nodes) {
|
||||
const rdonly = isOwner ? '' : 'readonly style="opacity:.5;cursor:default;"';
|
||||
html += `<div>
|
||||
<div class="vv-set-key" style="margin-bottom:4px;">${_vvSetEsc(n.id)}</div>
|
||||
<div class="vv-pt-set-key" style="margin-bottom:4px;">${_vvSetEsc(n.id)}</div>
|
||||
<input type="text" ${rdonly}
|
||||
class="vv-set-input vv-pt-host-inp"
|
||||
class="vv-pt-set-input vv-pt-host-inp"
|
||||
data-key="${_vvSetEsc(n.id)}" data-file="master.conf" data-type="scalar"
|
||||
data-orig="${_vvSetEsc(n.hostname)}"
|
||||
value="${_vvSetEsc(n.hostname)}"
|
||||
@@ -441,18 +441,18 @@ function _vvRenderArrayCards() {
|
||||
if (fld.type === 'scalar') continue;
|
||||
hasArrays = true;
|
||||
const rows = Math.min(16, (fld.value.match(/\n/g) || []).length + 2);
|
||||
const attrs = `class="vv-set-input" data-key="${_vvSetEsc(fld.key)}" `
|
||||
const attrs = `class="vv-pt-set-input" data-key="${_vvSetEsc(fld.key)}" `
|
||||
+ `data-file="${_vvSetEsc(fld.file)}" data-type="${_vvSetEsc(fld.type)}" `
|
||||
+ `data-orig="${_vvSetEsc(fld.value)}" oninput="vvPtArrChanged(this)"`;
|
||||
html += `<div class="vv-set-file">
|
||||
<div class="vv-set-file-hdr" onclick="vvPtToggleNode(this)">
|
||||
html += `<div class="vv-pt-set-file">
|
||||
<div class="vv-pt-set-file-hdr" onclick="vvPtToggleNode(this)">
|
||||
<span>${_vvSetEsc(fld.key)}</span>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
${fld.desc ? `<span style="font-size:9px;color:#444;font-weight:normal;font-family:inherit;">${_vvSetEsc(fld.desc)}</span>` : ''}
|
||||
<span class="vv-set-chev">▸</span>
|
||||
<span class="vv-pt-set-chev">▸</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vv-set-file-body" style="display:none;">
|
||||
<div class="vv-pt-set-file-body" style="display:none;">
|
||||
<textarea ${attrs} rows="${rows}">${_vvSetEsc(fld.value)}</textarea>
|
||||
</div>
|
||||
</div>`;
|
||||
@@ -476,13 +476,13 @@ function _vvRenderArrayCards() {
|
||||
|
||||
function vvPtArrChanged(el) {
|
||||
el.classList.toggle('changed', el.value !== el.dataset.orig);
|
||||
const any = document.querySelector('#vv-pt-arrays-wrap .vv-set-input.changed');
|
||||
const any = document.querySelector('#vv-pt-arrays-wrap .vv-pt-set-input.changed');
|
||||
const saveBtn = document.getElementById('vv-pt-arrays-save');
|
||||
if (saveBtn) saveBtn.style.display = any ? '' : 'none';
|
||||
}
|
||||
|
||||
async function vvPtSaveArrays(btn) {
|
||||
const changedEls = document.querySelectorAll('#vv-pt-arrays-wrap .vv-set-input.changed');
|
||||
const changedEls = document.querySelectorAll('#vv-pt-arrays-wrap .vv-pt-set-input.changed');
|
||||
if (!changedEls.length) return;
|
||||
const changes = [];
|
||||
changedEls.forEach(el => changes.push({key: el.dataset.key, file: el.dataset.file, type: el.dataset.type, value: el.value}));
|
||||
@@ -556,18 +556,18 @@ function vvPtRenderSettings(files) {
|
||||
const label = f.file === 'master.conf' ? 'master.conf — shared' : f.file + ' — this host';
|
||||
const scalarFields = f.groups.flatMap(g => g.fields.filter(fld => fld.type === 'scalar'));
|
||||
if (!scalarFields.length) continue;
|
||||
html += `<div class="vv-set-file">
|
||||
<div class="vv-set-file-hdr" onclick="vvPtToggleNode(this)">
|
||||
<span>${_vvSetEsc(label)}</span><span class="vv-set-chev">▾</span>
|
||||
html += `<div class="vv-pt-set-file">
|
||||
<div class="vv-pt-set-file-hdr" onclick="vvPtToggleNode(this)">
|
||||
<span>${_vvSetEsc(label)}</span><span class="vv-pt-set-chev">▾</span>
|
||||
</div>
|
||||
<div class="vv-set-file-body">`;
|
||||
<div class="vv-pt-set-file-body">`;
|
||||
for (const fld of scalarFields) {
|
||||
const attrs = `class="vv-set-input" data-key="${_vvSetEsc(fld.key)}" `
|
||||
const attrs = `class="vv-pt-set-input" data-key="${_vvSetEsc(fld.key)}" `
|
||||
+ `data-file="${_vvSetEsc(fld.file)}" data-type="${_vvSetEsc(fld.type)}" `
|
||||
+ `data-orig="${_vvSetEsc(fld.value)}" oninput="vvPtSetChanged(this)"`;
|
||||
html += `<div class="vv-set-field">
|
||||
<div class="vv-set-key">${_vvSetEsc(fld.key)}</div>`;
|
||||
if (fld.desc) html += `<div class="vv-set-desc">${_vvSetEsc(fld.desc)}</div>`;
|
||||
html += `<div class="vv-pt-set-field">
|
||||
<div class="vv-pt-set-key">${_vvSetEsc(fld.key)}</div>`;
|
||||
if (fld.desc) html += `<div class="vv-pt-set-desc">${_vvSetEsc(fld.desc)}</div>`;
|
||||
html += `<input type="text" ${attrs} value="${_vvSetEsc(fld.value)}"></div>`;
|
||||
}
|
||||
html += `</div></div>`;
|
||||
@@ -577,7 +577,7 @@ function vvPtRenderSettings(files) {
|
||||
|
||||
function vvPtToggleNode(hdr) {
|
||||
const body = hdr.nextElementSibling;
|
||||
const chev = hdr.querySelector('.vv-set-chev');
|
||||
const chev = hdr.querySelector('.vv-pt-set-chev');
|
||||
const open = body.style.display !== 'none';
|
||||
body.style.display = open ? 'none' : '';
|
||||
if (chev) chev.textContent = open ? '▸' : '▾';
|
||||
@@ -587,12 +587,12 @@ function vvPtSetChanged(el) {
|
||||
const changed = el.value !== el.dataset.orig;
|
||||
el.classList.toggle('changed', changed);
|
||||
// Show Save button if any field is changed
|
||||
const any = document.querySelector('#vv-pt-settings-body .vv-set-input.changed');
|
||||
const any = document.querySelector('#vv-pt-settings-body .vv-pt-set-input.changed');
|
||||
document.getElementById('vv-pt-settings-save').style.display = any ? '' : 'none';
|
||||
}
|
||||
|
||||
async function vvPtSaveSettings(btn) {
|
||||
const changedEls = document.querySelectorAll('#vv-pt-settings-body .vv-set-input.changed');
|
||||
const changedEls = document.querySelectorAll('#vv-pt-settings-body .vv-pt-set-input.changed');
|
||||
if (!changedEls.length) return;
|
||||
const changes = [];
|
||||
changedEls.forEach(el => changes.push({
|
||||
|
||||
Reference in New Issue
Block a user