mirror of
http://10.0.2.1:3031/sauer/bfa-dryer-design.git
synced 2026-06-30 13:06:42 +10:00
Card properties editor: name, type, color, font size, width, setpoints
This commit is contained in:
parent
b4033f210d
commit
4686458926
@ -184,6 +184,16 @@ body{font-family:'Segoe UI',system-ui,sans-serif;background:var(--bg);color:var(
|
||||
.auto-btns button{padding:10px 24px;border:none;border-radius:8px;font-size:16px;font-weight:600;cursor:pointer}
|
||||
.auto-btns .save-btn{background:var(--green);color:#000}
|
||||
.auto-btns .cancel-btn{background:var(--card);color:var(--text);border:1px solid var(--border)}
|
||||
|
||||
/* Card properties editor */
|
||||
.props-editor{width:420px;max-width:95vw}
|
||||
.props-editor h3{font-size:20px;margin-bottom:16px}
|
||||
.prop-row{display:flex;align-items:center;gap:12px;margin-bottom:12px}
|
||||
.prop-row label{width:100px;font-size:13px;color:var(--text2);flex-shrink:0;text-align:right}
|
||||
.prop-row input,.prop-row select{flex:1;padding:10px;border:1px solid var(--border);border-radius:6px;background:var(--card);color:var(--text);font-size:14px}
|
||||
.prop-row input[type=color]{width:50px;height:38px;padding:2px;cursor:pointer;flex:0}
|
||||
.prop-row input[type=range]{flex:1}
|
||||
.prop-preview{display:inline-block;width:24px;height:24px;border-radius:4px;border:1px solid var(--border);vertical-align:middle;margin-left:8px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -470,27 +480,28 @@ function createCardEl(c) {
|
||||
const commentCount = (layout.comments || []).filter(x => x.target === c.id).length;
|
||||
el.innerHTML += `<div class="card-comment-badge ${commentCount > 0 ? 'has-comments' : ''}">${commentCount}</div>`;
|
||||
|
||||
const cfs = c.fontSize || 18;
|
||||
if (c.type === 'temp') {
|
||||
const color = c.color || '#ff8844';
|
||||
el.innerHTML += `<div class="card-label" onclick="if(mode==='edit'){event.stopPropagation();renameCard('${c.id}')}">${c.label}</div>`;
|
||||
el.innerHTML += `<div class="card-label" style="font-size:${cfs}px" onclick="if(mode==='edit'){event.stopPropagation();editCardProps('${c.id}')}">${c.label}</div>`;
|
||||
el.innerHTML += `<div class="card-value" style="color:${color}">${Math.round(s.value)} °C</div>`;
|
||||
el.innerHTML += `<div class="card-bar"><div class="card-bar-fill" style="width:${Math.min(100,s.value/2)}%;background:${color}"></div></div>`;
|
||||
el.innerHTML += `<div class="card-sub">SP: ${c.sp_default || 70} °C</div>`;
|
||||
el.onclick = () => { if (mode === 'preview') openTempPopup(c); };
|
||||
} else if (c.type === 'motor') {
|
||||
el.innerHTML += `<div style="display:flex;gap:10px;align-items:center">
|
||||
<span class="card-label" onclick="if(mode==='edit'){event.stopPropagation();renameCard('${c.id}')}">${c.label}</span>
|
||||
<span class="card-label" style="font-size:${cfs}px" onclick="if(mode==='edit'){event.stopPropagation();editCardProps('${c.id}')}">${c.label}</span>
|
||||
<span style="font-size:18px;color:var(--text2)">${c.sp_default || 50}%</span>
|
||||
</div>`;
|
||||
el.innerHTML += `<div class="card-value">${s.on ? 'ON' : 'OFF'}</div>`;
|
||||
el.onclick = () => { if (mode === 'preview') toggleSim(c.id); };
|
||||
} else if (c.type === 'burner') {
|
||||
el.innerHTML += `<div class="card-label" onclick="if(mode==='edit'){event.stopPropagation();renameCard('${c.id}')}">${c.label}</div>`;
|
||||
el.innerHTML += `<div class="card-label" style="font-size:${cfs}px" onclick="if(mode==='edit'){event.stopPropagation();editCardProps('${c.id}')}">${c.label}</div>`;
|
||||
el.innerHTML += `<div class="card-value">${s.on ? 'ON' : 'OFF'}</div>`;
|
||||
el.onclick = () => { if (mode === 'preview') toggleSim(c.id); };
|
||||
} else if (c.type === 'automation') {
|
||||
// Automation card — combines outputs, speeds, temp setpoints
|
||||
el.innerHTML += `<div class="card-label" onclick="if(mode==='edit'){event.stopPropagation();renameCard('${c.id}')}" style="font-size:24px;font-weight:700">${c.label}</div>`;
|
||||
el.innerHTML += `<div class="card-label" onclick="if(mode==='edit'){event.stopPropagation();editCardProps('${c.id}')}" style="font-size:${Math.max(cfs,20)}px;font-weight:700">${c.label}</div>`;
|
||||
const rules = c.rules || [];
|
||||
if (rules.length === 0) {
|
||||
el.innerHTML += `<div class="card-sub" style="text-align:center">No rules configured<br>Click to edit in edit mode</div>`;
|
||||
@ -508,7 +519,7 @@ function createCardEl(c) {
|
||||
else if (mode === 'preview') toggleSim(c.id);
|
||||
};
|
||||
} else { // output
|
||||
el.innerHTML += `<div class="card-label" onclick="if(mode==='edit'){event.stopPropagation();renameCard('${c.id}')}" style="text-align:center">${c.label}</div>`;
|
||||
el.innerHTML += `<div class="card-label" onclick="if(mode==='edit'){event.stopPropagation();editCardProps('${c.id}')}" style="text-align:center;font-size:${cfs}px">${c.label}</div>`;
|
||||
el.innerHTML += `<div class="card-value">${s.on ? 'ON' : 'OFF'}</div>`;
|
||||
el.onclick = () => { if (mode === 'preview') toggleSim(c.id); };
|
||||
}
|
||||
@ -728,12 +739,89 @@ function deleteCard(id) {
|
||||
renderCards();
|
||||
}
|
||||
|
||||
function renameCard(id) {
|
||||
const page = layout.pages[currentPage];
|
||||
const card = page.cards.find(c => c.id === id);
|
||||
function editCardProps(id) {
|
||||
const card = findCard(id);
|
||||
if (!card) return;
|
||||
const name = prompt('New name:', card.label);
|
||||
if (name) { card.label = name; renderCards(); }
|
||||
|
||||
const p = document.getElementById('popup');
|
||||
p.style.borderColor = 'transparent';
|
||||
|
||||
let typeOpts = ['temp','motor','output','burner','automation'].map(t =>
|
||||
`<option value="${t}" ${card.type===t?'selected':''}>${t.charAt(0).toUpperCase()+t.slice(1)}</option>`
|
||||
).join('');
|
||||
|
||||
let extraFields = '';
|
||||
if (card.type === 'temp') {
|
||||
extraFields = `
|
||||
<div class="prop-row"><label>Setpoint</label><input type="number" id="prop-sp" value="${card.sp_default||70}" min="0" max="200"> <span style="color:var(--text2)">°C</span></div>`;
|
||||
} else if (card.type === 'motor') {
|
||||
extraFields = `
|
||||
<div class="prop-row"><label>Speed SP</label><input type="number" id="prop-sp" value="${card.sp_default||50}" min="0" max="100" step="5"> <span style="color:var(--text2)">%</span></div>`;
|
||||
}
|
||||
|
||||
p.innerHTML = `
|
||||
<div class="props-editor">
|
||||
<h3>Edit Card</h3>
|
||||
<div class="prop-row">
|
||||
<label>Name</label>
|
||||
<input type="text" id="prop-name" value="${card.label}">
|
||||
</div>
|
||||
<div class="prop-row">
|
||||
<label>Type</label>
|
||||
<select id="prop-type">${typeOpts}</select>
|
||||
</div>
|
||||
<div class="prop-row">
|
||||
<label>Size</label>
|
||||
<select id="prop-width">
|
||||
<option value="half" ${card.width!=='full'?'selected':''}>Half width</option>
|
||||
<option value="full" ${card.width==='full'?'selected':''}>Full width</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="prop-row">
|
||||
<label>Color</label>
|
||||
<input type="color" id="prop-color" value="${card.color||'#ff8844'}">
|
||||
<span class="prop-preview" id="prop-color-preview" style="background:${card.color||'#ff8844'}"></span>
|
||||
<button onclick="document.getElementById('prop-color').value='';document.getElementById('prop-color-preview').style.background='var(--card)'" style="padding:6px 10px;border:1px solid var(--border);border-radius:4px;background:var(--card);color:var(--text2);font-size:11px;cursor:pointer">Reset</button>
|
||||
</div>
|
||||
<div class="prop-row">
|
||||
<label>Font Size</label>
|
||||
<input type="range" id="prop-fontsize" min="12" max="36" value="${card.fontSize||18}">
|
||||
<span id="prop-fontsize-val" style="color:var(--text2);min-width:30px">${card.fontSize||18}px</span>
|
||||
</div>
|
||||
${extraFields}
|
||||
<div class="auto-btns">
|
||||
<button class="cancel-btn" onclick="closePopup()">Cancel</button>
|
||||
<button class="save-btn" onclick="saveCardProps('${id}')">Save</button>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
// Live preview for color picker
|
||||
document.getElementById('prop-color').addEventListener('input', e => {
|
||||
document.getElementById('prop-color-preview').style.background = e.target.value;
|
||||
});
|
||||
document.getElementById('prop-fontsize').addEventListener('input', e => {
|
||||
document.getElementById('prop-fontsize-val').textContent = e.target.value + 'px';
|
||||
});
|
||||
|
||||
document.getElementById('popup-overlay').classList.add('active');
|
||||
}
|
||||
|
||||
function saveCardProps(id) {
|
||||
const card = findCard(id);
|
||||
if (!card) return;
|
||||
|
||||
card.label = document.getElementById('prop-name').value || card.label;
|
||||
card.type = document.getElementById('prop-type').value;
|
||||
card.width = document.getElementById('prop-width').value;
|
||||
const color = document.getElementById('prop-color').value;
|
||||
card.color = color || null;
|
||||
card.fontSize = parseInt(document.getElementById('prop-fontsize').value) || 18;
|
||||
|
||||
const spEl = document.getElementById('prop-sp');
|
||||
if (spEl) card.sp_default = parseInt(spEl.value) || 0;
|
||||
|
||||
closePopup();
|
||||
renderCards();
|
||||
}
|
||||
|
||||
function toggleCardSize(id) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user