Add optional city scoping field to street exceptions UI

This commit is contained in:
zyphlar
2026-07-29 23:00:50 -07:00
parent 35d5185cbf
commit acdce05ec1
+16 -6
View File
@@ -214,7 +214,7 @@
<div class="card-header"> <div class="card-header">
<div> <div>
<h2>Street Name Exceptions</h2> <h2>Street Name Exceptions</h2>
<p>Applied to county address data after formatting, before comparison and import. Match is exact (case-sensitive).</p> <p>Applied to county address data after formatting, before comparison and import. Match is exact (case-sensitive). Leave City blank to apply everywhere.</p>
</div> </div>
</div> </div>
@@ -225,11 +225,12 @@
<tr> <tr>
<th>County data (from)</th> <th>County data (from)</th>
<th>Corrected name (to)</th> <th>Corrected name (to)</th>
<th>City (optional)</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody id="tableBody"> <tbody id="tableBody">
<tr><td colspan="3" style="padding:20px;text-align:center;color:#aaa;font-size:13px">Loading...</td></tr> <tr><td colspan="4" style="padding:20px;text-align:center;color:#aaa;font-size:13px">Loading...</td></tr>
</tbody> </tbody>
</table> </table>
@@ -261,7 +262,7 @@
function renderTable() { function renderTable() {
const tbody = document.getElementById('tableBody'); const tbody = document.getElementById('tableBody');
if (corrections.length === 0) { if (corrections.length === 0) {
tbody.innerHTML = '<tr><td colspan="3" style="padding:20px;text-align:center;color:#aaa;font-size:13px">No exceptions yet. Add a row to get started.</td></tr>'; tbody.innerHTML = '<tr><td colspan="4" style="padding:20px;text-align:center;color:#aaa;font-size:13px">No exceptions yet. Add a row to get started.</td></tr>';
return; return;
} }
tbody.innerHTML = corrections.map((c, i) => ` tbody.innerHTML = corrections.map((c, i) => `
@@ -270,6 +271,8 @@
oninput="corrections[${i}].from = this.value"></td> oninput="corrections[${i}].from = this.value"></td>
<td><input type="text" value="${esc(c.to)}" placeholder="Corrected street name" <td><input type="text" value="${esc(c.to)}" placeholder="Corrected street name"
oninput="corrections[${i}].to = this.value"></td> oninput="corrections[${i}].to = this.value"></td>
<td><input type="text" value="${esc(c.city)}" placeholder="Any city"
oninput="corrections[${i}].city = this.value"></td>
<td><button class="btn-delete" onclick="deleteRow(${i})" title="Delete">&#x2715;</button></td> <td><button class="btn-delete" onclick="deleteRow(${i})" title="Delete">&#x2715;</button></td>
</tr> </tr>
`).join(''); `).join('');
@@ -280,7 +283,7 @@
} }
function addRow() { function addRow() {
corrections.push({ from: '', to: '' }); corrections.push({ from: '', to: '', city: '' });
renderTable(); renderTable();
// Focus the new "from" input // Focus the new "from" input
const rows = document.getElementById('tableBody').querySelectorAll('tr'); const rows = document.getElementById('tableBody').querySelectorAll('tr');
@@ -301,6 +304,7 @@
const inputs = row.querySelectorAll('input'); const inputs = row.querySelectorAll('input');
corrections[i].from = inputs[0].value; corrections[i].from = inputs[0].value;
corrections[i].to = inputs[1].value; corrections[i].to = inputs[1].value;
corrections[i].city = inputs[2].value;
}); });
// Validate // Validate
@@ -311,10 +315,16 @@
} }
} }
// Drop blank city so the correction applies everywhere, not nowhere
const payload = corrections.map(c => {
const { city, ...rest } = c;
return city && city.trim() ? { ...rest, city: city.trim() } : rest;
});
fetch('/api/exceptions', { fetch('/api/exceptions', {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ corrections }) body: JSON.stringify({ corrections: payload })
}) })
.then(r => r.json()) .then(r => r.json())
.then(data => { .then(data => {
@@ -352,7 +362,7 @@
}) })
.catch(err => { .catch(err => {
document.getElementById('tableBody').innerHTML = document.getElementById('tableBody').innerHTML =
`<tr><td colspan="3" style="padding:20px;text-align:center;color:#c00">Failed to load: ${err.message}</td></tr>`; `<tr><td colspan="4" style="padding:20px;text-align:center;color:#c00">Failed to load: ${err.message}</td></tr>`;
}); });
</script> </script>
</body> </body>