Add optional city scoping field to street exceptions UI
This commit is contained in:
@@ -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">✕</button></td>
|
<td><button class="btn-delete" onclick="deleteRow(${i})" title="Delete">✕</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>
|
||||||
|
|||||||
Reference in New Issue
Block a user