Move config download/upload into Counties and Exceptions pages
This commit is contained in:
+2
-2
@@ -503,7 +503,7 @@ def get_counties():
|
|||||||
|
|
||||||
@app.route('/counties')
|
@app.route('/counties')
|
||||||
def counties_page():
|
def counties_page():
|
||||||
return render_template('counties.html')
|
return render_template('counties.html', current_user=session.get('username'))
|
||||||
|
|
||||||
@app.route('/api/counties', methods=['GET'])
|
@app.route('/api/counties', methods=['GET'])
|
||||||
def get_counties_api():
|
def get_counties_api():
|
||||||
@@ -555,7 +555,7 @@ _ensure_exceptions_file()
|
|||||||
|
|
||||||
@app.route('/exceptions')
|
@app.route('/exceptions')
|
||||||
def exceptions_page():
|
def exceptions_page():
|
||||||
return render_template('exceptions.html')
|
return render_template('exceptions.html', current_user=session.get('username'))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/exceptions', methods=['GET'])
|
@app.route('/api/exceptions', methods=['GET'])
|
||||||
|
|||||||
@@ -181,6 +181,19 @@
|
|||||||
.btn-add:hover { background: #c8e6c9; }
|
.btn-add:hover { background: #c8e6c9; }
|
||||||
.btn-save { background: #17a2b8; color: white; }
|
.btn-save { background: #17a2b8; color: white; }
|
||||||
.btn-save:hover { filter: brightness(0.9); }
|
.btn-save:hover { filter: brightness(0.9); }
|
||||||
|
|
||||||
|
.btn-dl {
|
||||||
|
padding: 7px 12px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: #e9ecef;
|
||||||
|
color: #555;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.btn-dl:hover { background: #dee2e6; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -205,6 +218,11 @@
|
|||||||
<div class="footer">
|
<div class="footer">
|
||||||
<button class="btn btn-add" onclick="addCounty()">+ Add county</button>
|
<button class="btn btn-add" onclick="addCounty()">+ Add county</button>
|
||||||
<button class="btn btn-save" onclick="save()">Save</button>
|
<button class="btn btn-save" onclick="save()">Save</button>
|
||||||
|
{% if current_user %}
|
||||||
|
<div style="flex:1"></div>
|
||||||
|
<a href="/api/config/counties.yml" class="btn-dl" title="Download counties.yml">↓ Download</a>
|
||||||
|
<label class="btn-dl" style="cursor:pointer" title="Upload counties.yml">↑ Upload<input type="file" style="display:none" accept=".yml,.yaml" onchange="uploadConfig(this)"></label>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -338,6 +356,22 @@
|
|||||||
.catch(err => showStatus(`Error: ${err.message}`, 'error'));
|
.catch(err => showStatus(`Error: ${err.message}`, 'error'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uploadConfig(input) {
|
||||||
|
if (!input.files.length) return;
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', input.files[0]);
|
||||||
|
showStatus('Uploading…', 'success');
|
||||||
|
fetch('/api/config/counties.yml', { method: 'POST', body: formData })
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) { showStatus(`Error: ${data.error}`, 'error'); return; }
|
||||||
|
showStatus('Uploaded — reloading…', 'success');
|
||||||
|
setTimeout(() => window.location.reload(), 800);
|
||||||
|
})
|
||||||
|
.catch(err => showStatus(`Error: ${err.message}`, 'error'))
|
||||||
|
.finally(() => { input.value = ''; });
|
||||||
|
}
|
||||||
|
|
||||||
// Load on open
|
// Load on open
|
||||||
fetch('/api/counties')
|
fetch('/api/counties')
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
|
|||||||
@@ -180,6 +180,19 @@
|
|||||||
|
|
||||||
.btn-save { background: #17a2b8; color: white; }
|
.btn-save { background: #17a2b8; color: white; }
|
||||||
.btn-save:hover { filter: brightness(0.9); }
|
.btn-save:hover { filter: brightness(0.9); }
|
||||||
|
|
||||||
|
.btn-dl {
|
||||||
|
padding: 7px 12px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: #e9ecef;
|
||||||
|
color: #555;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.btn-dl:hover { background: #dee2e6; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -222,6 +235,11 @@
|
|||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<button class="btn btn-add" onclick="addRow()">+ Add row</button>
|
<button class="btn btn-add" onclick="addRow()">+ Add row</button>
|
||||||
<button class="btn btn-save" onclick="save()">Save</button>
|
<button class="btn btn-save" onclick="save()">Save</button>
|
||||||
|
{% if current_user %}
|
||||||
|
<div style="flex:1"></div>
|
||||||
|
<a href="/api/config/exceptions.yml" class="btn-dl" title="Download exceptions.yml">↓ Download</a>
|
||||||
|
<label class="btn-dl" style="cursor:pointer" title="Upload exceptions.yml">↑ Upload<input type="file" style="display:none" accept=".yml,.yaml" onchange="uploadConfig(this)"></label>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -308,6 +326,22 @@
|
|||||||
.catch(err => showStatus(`Error: ${err.message}`, 'error'));
|
.catch(err => showStatus(`Error: ${err.message}`, 'error'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uploadConfig(input) {
|
||||||
|
if (!input.files.length) return;
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', input.files[0]);
|
||||||
|
showStatus('Uploading…', 'info');
|
||||||
|
fetch('/api/config/exceptions.yml', { method: 'POST', body: formData })
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) { showStatus(`Error: ${data.error}`, 'error'); return; }
|
||||||
|
showStatus('Uploaded — reloading…', 'success');
|
||||||
|
setTimeout(() => window.location.reload(), 800);
|
||||||
|
})
|
||||||
|
.catch(err => showStatus(`Error: ${err.message}`, 'error'))
|
||||||
|
.finally(() => { input.value = ''; });
|
||||||
|
}
|
||||||
|
|
||||||
// Load on page open
|
// Load on page open
|
||||||
fetch('/api/exceptions')
|
fetch('/api/exceptions')
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
|
|||||||
@@ -65,26 +65,6 @@
|
|||||||
|
|
||||||
.btn-topbar.purple:hover { background: #5a32a3; }
|
.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 two-panel layout ── */
|
||||||
.main {
|
.main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -378,17 +358,6 @@
|
|||||||
<button class="btn-topbar" onclick="runScript('ls', '')">List Files</button>
|
<button class="btn-topbar" onclick="runScript('ls', '')">List Files</button>
|
||||||
<button class="btn-topbar" onclick="clearData()" style="color:#f88;">Clear Data</button>
|
<button class="btn-topbar" onclick="clearData()" style="color:#f88;">Clear Data</button>
|
||||||
<div style="flex:1"></div>
|
<div style="flex:1"></div>
|
||||||
{% if current_user %}
|
|
||||||
<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>
|
|
||||||
{% endif %}
|
|
||||||
<a href="/counties" class="btn-topbar">Counties</a>
|
<a href="/counties" class="btn-topbar">Counties</a>
|
||||||
<a href="/exceptions" class="btn-topbar">Street Exceptions</a>
|
<a href="/exceptions" class="btn-topbar">Street Exceptions</a>
|
||||||
<a href="/map" class="btn-topbar purple">Open Map Viewer</a>
|
<a href="/map" class="btn-topbar purple">Open Map Viewer</a>
|
||||||
@@ -762,25 +731,6 @@
|
|||||||
.catch(err => showStatus(`Error: ${err.message}`, 'error'));
|
.catch(err => showStatus(`Error: ${err.message}`, 'error'));
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
function showStatus(msg, type) {
|
||||||
const el = document.getElementById('status');
|
const el = document.getElementById('status');
|
||||||
el.textContent = msg;
|
el.textContent = msg;
|
||||||
|
|||||||
Reference in New Issue
Block a user