Flatten to /data/latest, add mtimes, add config download/upload

This commit is contained in:
zyphlar
2026-04-21 22:49:45 -07:00
parent 7d6fc1c62e
commit 7aaff6be35
2 changed files with 150 additions and 65 deletions
+52 -5
View File
@@ -65,6 +65,26 @@
.btn-topbar.purple:hover { background: #5a32a3; }
.btn-topbar-icon {
padding: 5px 8px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 12px;
font-weight: 600;
background: #ffffff18;
color: #ddd;
text-decoration: none;
}
.btn-topbar-icon:hover { background: #ffffff30; }
.config-group {
display: flex;
align-items: center;
gap: 2px;
}
/* ── Main two-panel layout ── */
.main {
flex: 1;
@@ -355,9 +375,17 @@
<div class="topbar">
<h1>OSM Import Tools</h1>
<div class="topbar-sep"></div>
<button class="btn-topbar" onclick="runScript('make-new-latest', '')">New Latest</button>
<button class="btn-topbar" onclick="runScript('ls', '')">List Files</button>
<div style="flex:1"></div>
<div class="config-group">
<a href="/api/config/counties.yml" class="btn-topbar-icon" title="Download counties.yml">↓ counties.yml</a>
<label class="btn-topbar-icon" title="Upload counties.yml" style="cursor:pointer"><input type="file" style="display:none" accept=".yml,.yaml" onchange="uploadConfig('counties.yml', this)"></label>
</div>
<div class="config-group">
<a href="/api/config/exceptions.yml" class="btn-topbar-icon" title="Download exceptions.yml">↓ exceptions.yml</a>
<label class="btn-topbar-icon" title="Upload exceptions.yml" style="cursor:pointer"><input type="file" style="display:none" accept=".yml,.yaml" onchange="uploadConfig('exceptions.yml', this)"></label>
</div>
<div class="topbar-sep"></div>
<a href="/counties" class="btn-topbar">Counties</a>
<a href="/exceptions" class="btn-topbar">Street Exceptions</a>
<a href="/map" class="btn-topbar purple">Open Map Viewer</a>
@@ -489,11 +517,11 @@
<div class="file-links">
{% for county in counties %}
{% if county.id in data_files %}
{% for file_name in data_files[county.id] %}
{% for file in data_files[county.id] %}
<a class="file-link"
style="--link-color: {{ county.color }}"
href="/data/latest/{{ county.id }}/{{ file_name }}"
title="{{ county.id }}/{{ file_name }}">{{ file_name }}</a>
href="/data/{{ county.id }}/{{ file.name }}"
title="{{ county.id }}/{{ file.name }} — {{ file.mtime }}">{{ file.name }}</a>
{% endfor %}
{% endif %}
{% endfor %}
@@ -568,7 +596,7 @@
// Step 1: upload or download
const inputId = `upload-${county}-paths`;
const dest = `/data/latest/${county}/paths.shp.zip`;
const dest = `/data/${county}/paths.shp.zip`;
if (pathsUrl === 'upload') {
document.getElementById('paths-step-1-actions').innerHTML =
`<input type="file" id="${inputId}" class="upload-input" accept=".zip">` +
@@ -697,6 +725,25 @@
.finally(() => enableButtons());
}
function uploadConfig(filename, input) {
if (!input.files.length) return;
const formData = new FormData();
formData.append('file', input.files[0]);
showStatus(`Uploading ${filename}...`, 'info');
fetch(`/api/config/${filename}`, { method: 'POST', body: formData })
.then(r => r.json())
.then(data => {
if (data.error) {
showStatus(`Error: ${data.error}`, 'error');
} else {
showStatus(`${filename} uploaded successfully.`, 'success');
setTimeout(() => window.location.reload(), 800);
}
})
.catch(err => showStatus(`Error: ${err.message}`, 'error'))
.finally(() => { input.value = ''; });
}
function showStatus(msg, type) {
const el = document.getElementById('status');
el.textContent = msg;