Add Docker/Compose setup and fix subpath routing for /toroid deployment
- Add Dockerfile, .dockerignore, and docker-compose.yml to containerize the app - Add toroid.service systemd unit (uses docker compose) - Mount presets/ as a bind volume for persistence outside the container - Fix all fetch() calls in templates to use relative paths (no leading /) so they resolve correctly when served under /toroid/ via nginx proxy Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -772,7 +772,7 @@ async function runDesign() {
|
||||
|
||||
try {
|
||||
const payload = buildPayload();
|
||||
const resp = await fetch('/api/design', {
|
||||
const resp = await fetch('api/design', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(payload),
|
||||
@@ -901,7 +901,7 @@ async function runOperatingPoint() {
|
||||
constraints: collectConstraints(),
|
||||
});
|
||||
|
||||
const resp = await fetch('/api/simulate', {
|
||||
const resp = await fetch('api/simulate', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(payload),
|
||||
@@ -1001,7 +1001,7 @@ async function runSweep() {
|
||||
},
|
||||
});
|
||||
|
||||
const resp = await fetch('/api/sweep', {
|
||||
const resp = await fetch('api/sweep', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(payload),
|
||||
@@ -1463,7 +1463,7 @@ function presetApply(ptype, data) {
|
||||
async function presetRefresh(ptype) {
|
||||
const sel = document.getElementById(`preset-sel-${ptype}`);
|
||||
if (!sel) return null;
|
||||
const resp = await fetch(`/api/presets/${ptype}`);
|
||||
const resp = await fetch(`api/presets/${ptype}`);
|
||||
const data = await resp.json();
|
||||
if (!data.success) return null;
|
||||
sel.innerHTML = data.names.length === 0
|
||||
@@ -1479,7 +1479,7 @@ async function presetLoad(ptype) {
|
||||
const sel = document.getElementById(`preset-sel-${ptype}`);
|
||||
const name = sel ? sel.value : '';
|
||||
if (!name) return;
|
||||
const resp = await fetch(`/api/presets/${ptype}/${encodeURIComponent(name)}`);
|
||||
const resp = await fetch(`api/presets/${ptype}/${encodeURIComponent(name)}`);
|
||||
const data = await resp.json();
|
||||
if (!data.success) { alert('Load failed: ' + data.error); return; }
|
||||
presetApply(ptype, data.data);
|
||||
@@ -1493,7 +1493,7 @@ async function presetSave(ptype) {
|
||||
const name = nameEl ? nameEl.value.trim() : '';
|
||||
if (!name) { alert('Enter a preset name first.'); return; }
|
||||
const payload = presetExtract(ptype);
|
||||
const resp = await fetch(`/api/presets/${ptype}/${encodeURIComponent(name)}`, {
|
||||
const resp = await fetch(`api/presets/${ptype}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(payload),
|
||||
@@ -1511,7 +1511,7 @@ async function presetDelete(ptype) {
|
||||
const name = sel ? sel.value : '';
|
||||
if (!name || name === '(no saved presets)') return;
|
||||
if (!confirm(`Delete preset "${name}"?`)) return;
|
||||
const resp = await fetch(`/api/presets/${ptype}/${encodeURIComponent(name)}`, { method: 'DELETE' });
|
||||
const resp = await fetch(`api/presets/${ptype}/${encodeURIComponent(name)}`, { method: 'DELETE' });
|
||||
const data = await resp.json();
|
||||
if (!data.success) { alert('Delete failed: ' + data.error); return; }
|
||||
await presetRefresh(ptype);
|
||||
@@ -1523,7 +1523,7 @@ async function initPresets() {
|
||||
const info = await presetRefresh(ptype);
|
||||
if (info && info.last) {
|
||||
// Auto-load last used
|
||||
const resp = await fetch(`/api/presets/${ptype}/${encodeURIComponent(info.last)}`);
|
||||
const resp = await fetch(`api/presets/${ptype}/${encodeURIComponent(info.last)}`);
|
||||
const d = await resp.json();
|
||||
if (d.success) presetApply(ptype, d.data);
|
||||
}
|
||||
@@ -1536,7 +1536,7 @@ async function initPresets() {
|
||||
(async () => {
|
||||
// initPresets returns after applying last-used presets (if any)
|
||||
const windingsInfo = await (async () => {
|
||||
const r = await fetch('/api/presets/windings');
|
||||
const r = await fetch('api/presets/windings');
|
||||
const d = await r.json();
|
||||
return d.success ? d : null;
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user