Files
mimaki/webui/static/app.js
Lukas Cremer cd846577a4 add webui
2026-02-03 22:41:29 +01:00

254 lines
9.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function () {
const fileInput = document.getElementById('fileInput');
const preview = document.getElementById('preview');
const previewPlaceholder = document.getElementById('previewPlaceholder');
const statusFile = document.getElementById('statusFile');
const statusPlotter = document.getElementById('statusPlotter');
const printMessage = document.getElementById('printMessage');
const scaleDims = document.getElementById('scaleDims');
const plotterInfo = {
port: document.getElementById('plotterPort'),
baud: document.getElementById('plotterBaud'),
winsizeUnits: document.getElementById('plotterWinsizeUnits'),
winsizeMm: document.getElementById('plotterWinsizeMm'),
bounds: document.getElementById('plotterBounds')
};
const buttons = {
flip: document.getElementById('btnFlip'),
rotate90: document.getElementById('btnRotate90'),
rotate180: document.getElementById('btnRotate180'),
scaleUp: document.getElementById('btnScaleUp'),
scaleDown: document.getElementById('btnScaleDown'),
centralize: document.getElementById('btnCentralize'),
scaleToBounds: document.getElementById('btnScaleToBounds'),
print: document.getElementById('btnPrint'),
checkPlotter: document.getElementById('btnCheckPlotter')
};
function setMessage(el, text, type) {
el.textContent = text || '';
el.className = 'message' + (type ? ' ' + type : '');
}
function updatePreview() {
const w = Math.min(800, window.innerWidth - 80);
const h = Math.min(600, window.innerHeight - 120);
preview.src = '/api/svg?width=' + w + '&height=' + h + '&scale=1&_=' + Date.now();
}
function updateDimensions() {
if (!scaleDims) return;
fetch('/api/dimensions')
.then(function (r) {
if (!r.ok) throw new Error();
return r.json();
})
.then(function (d) {
scaleDims.innerHTML = d.width + ' × ' + d.height + ' <span class="unit">(≈ ' + d.width_mm + ' × ' + d.height_mm + ' mm)</span>';
})
.catch(function () {
scaleDims.innerHTML = '— × — <span class="unit">(≈ — × — mm)</span>';
});
}
function updatePlotterInfo() {
if (!plotterInfo.port) return;
fetch('/api/plotter_info')
.then(function (r) { return r.ok ? r.json() : Promise.reject(); })
.then(function (d) {
plotterInfo.port.textContent = d.port || '—';
plotterInfo.baud.textContent = d.baudrate ? d.baudrate + ' baud' : '—';
if (d.winsize_units) {
plotterInfo.winsizeUnits.textContent = d.winsize_units.width + ' × ' + d.winsize_units.height;
} else {
plotterInfo.winsizeUnits.textContent = '— × —';
}
if (d.winsize_mm) {
plotterInfo.winsizeMm.textContent = d.winsize_mm.width + ' × ' + d.winsize_mm.height + ' mm';
} else {
plotterInfo.winsizeMm.textContent = '— × —';
}
if (d.boundaries) {
var b = d.boundaries;
plotterInfo.bounds.textContent = b.xmin + ',' + b.ymin + ' … ' + b.xmax + ',' + b.ymax;
} else {
plotterInfo.bounds.textContent = '—';
}
})
.catch(function () {
plotterInfo.port.textContent = '—';
plotterInfo.baud.textContent = '—';
plotterInfo.winsizeUnits.textContent = '— × —';
plotterInfo.winsizeMm.textContent = '— × —';
plotterInfo.bounds.textContent = '—';
});
}
function setLoaded(loaded) {
if (loaded) {
preview.classList.add('loaded');
previewPlaceholder.classList.add('hidden');
Object.keys(buttons).forEach(function (k) {
var b = buttons[k];
if (b) b.disabled = false;
});
} else {
preview.classList.remove('loaded');
previewPlaceholder.classList.remove('hidden');
preview.src = '';
Object.keys(buttons).forEach(function (k) {
var b = buttons[k];
if (b) b.disabled = true;
});
}
}
function refreshStatus() {
fetch('/api/status')
.then(function (r) { return r.json(); })
.then(function (data) {
statusFile.textContent = data.has_file ? (data.filename || 'File loaded') : 'No file';
statusPlotter.textContent = 'Plotter: ' + (data.plotter_ready ? 'Ready' : 'Not connected');
statusPlotter.classList.toggle('ready', data.plotter_ready);
statusPlotter.classList.toggle('not-ready', !data.plotter_ready);
updatePlotterInfo();
if (data.has_file) {
setLoaded(true);
updatePreview();
updateDimensions();
} else {
setLoaded(false);
if (scaleDims) scaleDims.innerHTML = '— × — <span class="unit">(≈ — × — mm)</span>';
}
})
.catch(function () {
statusFile.textContent = 'No file';
statusPlotter.textContent = 'Plotter: —';
setLoaded(false);
if (scaleDims) scaleDims.innerHTML = '— × — <span class="unit">(≈ — × — mm)</span>';
});
}
fileInput.addEventListener('change', function () {
const file = this.files && this.files[0];
if (!file) return;
preview.src = '';
preview.classList.remove('loaded');
previewPlaceholder.classList.remove('hidden');
previewPlaceholder.textContent = 'Loading…';
setMessage(printMessage, '');
const form = new FormData();
form.append('file', file);
fetch('/api/upload', {
method: 'POST',
body: form
})
.then(function (r) {
if (!r.ok) return r.json().then(function (d) { throw new Error(d.error || 'Upload failed'); });
return r.json();
})
.then(function () {
previewPlaceholder.textContent = 'Upload an HPGL file to preview';
refreshStatus();
})
.catch(function (e) {
previewPlaceholder.textContent = 'Upload an HPGL file to preview';
setMessage(printMessage, e.message || 'Upload failed', 'error');
refreshStatus();
});
});
function transform(action, payload) {
setMessage(printMessage, '');
var body = payload || { action: action };
fetch('/api/transform', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
})
.then(function (r) {
if (!r.ok) return r.json().then(function (d) { throw new Error(d.error || 'Transform failed'); });
return r.json();
})
.then(function () {
updatePreview();
updateDimensions();
})
.catch(function (e) {
setMessage(printMessage, e.message || 'Transform failed', 'error');
});
}
buttons.flip.addEventListener('click', function () { transform('flip'); });
buttons.rotate90.addEventListener('click', function () { transform('rotate', { action: 'rotate', angle: 90 }); });
buttons.rotate180.addEventListener('click', function () { transform('rotate', { action: 'rotate', angle: 180 }); });
buttons.scaleUp.addEventListener('click', function () { transform('scale', { action: 'scale', factor: 1.25 }); });
buttons.scaleDown.addEventListener('click', function () { transform('scale', { action: 'scale', factor: 0.8 }); });
buttons.centralize.addEventListener('click', function () { transform('centralize'); });
if (buttons.scaleToBounds) {
buttons.scaleToBounds.addEventListener('click', function () {
setMessage(printMessage, '');
fetch('/api/status')
.then(function (r) { return r.json(); })
.then(function (data) {
if (!data.plotter_ready) {
setMessage(printMessage, 'Plotter not connected.', 'error');
return;
}
transform('scale_to_bounds', { action: 'scale_to_bounds' });
})
.catch(function () {
setMessage(printMessage, 'Plotter not connected.', 'error');
});
});
}
buttons.print.addEventListener('click', function () {
setMessage(printMessage, 'Sending to plotter…');
fetch('/api/print', { method: 'POST' })
.then(function (r) {
return r.json().then(function (data) {
if (!r.ok) throw new Error(data.error || 'Print failed');
return data;
});
})
.then(function () {
setMessage(printMessage, 'Sent to plotter.', 'success');
})
.catch(function (e) {
setMessage(printMessage, e.message || 'Print failed', 'error');
});
});
if (buttons.checkPlotter) {
buttons.checkPlotter.addEventListener('click', function () {
setMessage(printMessage, 'Checking plotter…');
fetch('/api/status')
.then(function (r) { return r.json(); })
.then(function (data) {
statusFile.textContent = data.has_file ? (data.filename || 'File loaded') : 'No file';
statusPlotter.textContent = 'Plotter: ' + (data.plotter_ready ? 'Ready' : 'Not connected');
statusPlotter.classList.toggle('ready', data.plotter_ready);
statusPlotter.classList.toggle('not-ready', !data.plotter_ready);
updatePlotterInfo();
setMessage(printMessage, data.plotter_ready ? 'Plotter: Ready' : 'Plotter: Not connected', data.plotter_ready ? 'success' : 'error');
})
.catch(function () {
statusPlotter.textContent = 'Plotter: —';
statusPlotter.classList.remove('ready');
statusPlotter.classList.add('not-ready');
updatePlotterInfo();
setMessage(printMessage, 'Plotter: Not connected', 'error');
});
});
}
preview.addEventListener('load', function () {
previewPlaceholder.classList.add('hidden');
});
refreshStatus();
updatePlotterInfo();
setInterval(updatePlotterInfo, 10000);
})();