Merge the partnership settings into one section, arrays and scalars together
They were two sections drawing the same endpoint, split on whether a value happened to be a list — with two Save buttons for one subject.
This commit is contained in:
@@ -172,8 +172,6 @@ textarea.vv-pt-set-input { resize:vertical; white-space:pre; }
|
||||
Collapsed together they cost one line until opened. -->
|
||||
<div id="vv-pt-settings-body" style="display:none;margin-top:10px;">
|
||||
|
||||
<div id="vv-pt-arrays-wrap" style="display:none;margin-bottom:16px;"></div>
|
||||
|
||||
<div id="vv-pt-settings-conf"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -418,103 +416,10 @@ async function vvPtStopSeed(btn) {
|
||||
|
||||
// ── Array settings cards ───────────────────────────────────────────────────────
|
||||
|
||||
let _vvArrFiles = null;
|
||||
|
||||
function _vvInitArrayCards() {
|
||||
if (_vvArrFiles !== null) return;
|
||||
_vvArrFiles = false; // loading sentinel
|
||||
fetch('/plugins/varaverk/api/partnership_settings.php?_=' + Date.now())
|
||||
.then(r => r.json())
|
||||
.then(d => {
|
||||
_vvArrFiles = (d.ok && d.files) ? d.files : [];
|
||||
_vvRenderArrayCards();
|
||||
})
|
||||
.catch(() => { _vvArrFiles = []; document.getElementById('vv-pt-arrays-wrap').style.display = 'none'; });
|
||||
}
|
||||
|
||||
function _vvRenderArrayCards() {
|
||||
const files = _vvArrFiles;
|
||||
if (!files || !files.length) { document.getElementById('vv-pt-arrays-wrap').style.display = 'none'; return; }
|
||||
|
||||
let html = '';
|
||||
let hasArrays = false;
|
||||
for (const f of files) {
|
||||
for (const g of f.groups) {
|
||||
for (const fld of g.fields) {
|
||||
if (fld.type === 'scalar') continue;
|
||||
hasArrays = true;
|
||||
const rows = Math.min(16, (fld.value.match(/\n/g) || []).length + 2);
|
||||
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-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-pt-set-chev">▸</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vv-pt-set-file-body" style="display:none;">
|
||||
<textarea ${attrs} rows="${rows}">${_vvSetEsc(fld.value)}</textarea>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrap = document.getElementById('vv-pt-arrays-wrap');
|
||||
if (!hasArrays) { wrap.style.display = 'none'; return; }
|
||||
|
||||
wrap.style.display = '';
|
||||
wrap.innerHTML = `<div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
|
||||
<div class="vv-cl-title" style="margin:0;">Array settings</div>
|
||||
<button id="vv-pt-arrays-save" class="vv-pt-action-btn run"
|
||||
onclick="vvPtSaveArrays(this)" style="display:none;">Save Changes</button>
|
||||
</div>
|
||||
${html}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function vvPtArrChanged(el) {
|
||||
el.classList.toggle('changed', el.value !== el.dataset.orig);
|
||||
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-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}));
|
||||
if (!await vvConfirm(`Save ${changes.length} changed setting(s)?`)) return;
|
||||
btn.disabled = true; btn.textContent = '⟳ Saving…';
|
||||
fetch('/plugins/varaverk/api/confform.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token: typeof csrf_token !== 'undefined' ? csrf_token : '',
|
||||
id: '__settings__',
|
||||
changes: JSON.stringify(changes)
|
||||
})
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(d => {
|
||||
btn.disabled = false;
|
||||
if (d.ok) {
|
||||
changedEls.forEach(el => { el.dataset.orig = el.value; el.classList.remove('changed'); });
|
||||
btn.textContent = '✓ Saved';
|
||||
_vvArrFiles = null; // invalidate so next init re-fetches
|
||||
setTimeout(() => _vvInitArrayCards(), 600);
|
||||
} else {
|
||||
btn.textContent = 'Save Changes';
|
||||
vvAlert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
}
|
||||
})
|
||||
.catch(e => { btn.disabled = false; btn.textContent = 'Save Changes'; vvAlert('Error: ' + e); });
|
||||
}
|
||||
|
||||
// ── Settings panel ─────────────────────────────────────────────────────────────
|
||||
let _vvSetLoaded = false;
|
||||
@@ -555,29 +460,43 @@ function vvPtLoadSettings() {
|
||||
.catch(e => { body.innerHTML = '<div style="color:#f88;font-size:12px;padding:8px 0;">Error: ' + e + '</div>'; });
|
||||
}
|
||||
|
||||
// Every partnership field, scalars and arrays together, in the order the conf declares them.
|
||||
//
|
||||
// These were two sections drawing the same endpoint and splitting it on whether a value happened
|
||||
// to be a list: 25 scalars under "Partnership settings", 10 arrays under "Array settings", each
|
||||
// with its own Save. Nothing about the subject is divided that way — PROVISION_SHARES and
|
||||
// PARTNERSHIP_ENABLED are the same conversation — and the split meant looking in two places for
|
||||
// one setting, with the arrays half easy to mistake for something belonging to another page.
|
||||
//
|
||||
// Both render into the same .vv-pt-set-field wrapper so a list and a value read as siblings; the
|
||||
// only difference is a textarea instead of an input, sized to the content.
|
||||
function vvPtRenderSettings(files) {
|
||||
let html = '';
|
||||
for (const f of 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;
|
||||
const fields = f.groups.flatMap(g => g.fields);
|
||||
if (!fields.length) continue;
|
||||
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-pt-set-file-body">`;
|
||||
for (const fld of scalarFields) {
|
||||
for (const fld of fields) {
|
||||
const isArr = fld.type !== 'scalar';
|
||||
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-pt-set-field">
|
||||
<div class="vv-pt-set-key">${_vvSetEsc(fld.key)}</div>`;
|
||||
<div class="vv-pt-set-key">${_vvSetEsc(fld.key)}${isArr ? ' <span style="color:#3a3a3a;font-weight:normal;">list</span>' : ''}</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 += isArr
|
||||
? `<textarea ${attrs} rows="${Math.min(16, (fld.value.match(/\n/g) || []).length + 2)}">${_vvSetEsc(fld.value)}</textarea>`
|
||||
: `<input type="text" ${attrs} value="${_vvSetEsc(fld.value)}">`;
|
||||
html += `</div>`;
|
||||
}
|
||||
html += `</div></div>`;
|
||||
}
|
||||
return html || '<div style="color:#555;font-size:12px;padding:8px 0;">No scalar settings available.</div>';
|
||||
return html || '<div style="color:#555;font-size:12px;padding:8px 0;">No settings available.</div>';
|
||||
}
|
||||
|
||||
function vvPtToggleNode(hdr) {
|
||||
@@ -1304,8 +1223,6 @@ function _render(data) {
|
||||
// Actions
|
||||
document.getElementById('vv-pt-actions-body').innerHTML = _renderActions(nodes, cfg);
|
||||
|
||||
// Array settings cards above Actions — load once
|
||||
_vvInitArrayCards();
|
||||
|
||||
// Settings panel — host1 only
|
||||
document.getElementById('vv-pt-settings-card').style.display = isOwner ? '' : 'none';
|
||||
|
||||
Reference in New Issue
Block a user