nidus-sync/html/template/sync/upload-by-id.html
Eli Ribble c039c70e3e
Switch file upload page to not use map-libre-test
That libre test was something I built when doing the changeover to
stadia maps. It's now pretty well baked, so it's better to just use it.
2026-03-19 03:30:01 +00:00

216 lines
6.5 KiB
HTML

{{ template "sync/layout/authenticated.html" . }}
{{ define "title" }}Pool Upload{{ end }}
{{ define "extraheader" }}
<script
type="text/javascript"
src="//unpkg.com/maplibre-gl@5.0.1/dist/maplibre-gl.js"
></script>
<script src="/static/js/map-multipoint.js"></script>
<script>
const CSV_FILE_ID={{.C.CSVFileID}};
const ORG_ID={{.Organization.ID}};
function handleShowIssuesOnly() {
const checkboxShowIssuesOnly = document.getElementById("showIssuesOnly");
const allRows = document.querySelectorAll('tr');
if (checkboxShowIssuesOnly.checked) {
allRows.forEach(row => {
if (!(row.classList.contains("has-error") || row.classList.contains("header"))) {
row.style.display = "none";
}
});
} else {
allRows.forEach(row => {
row.style.display = "table-row";
});
}
}
function onLoad() {
const map = document.querySelector("map-multipoint");
map.addEventListener("load", (event) => {
map.addSource('tegola-nidus', {
'type': 'vector',
'tiles': [
`{{.URL.Tegola}}maps/nidus/{z}/{x}/{y}?csv_file=${CSV_FILE_ID}&id=${ORG_ID}`
]
});
map.addLayer({
'id': 'pool',
'source': 'tegola-nidus',
'source-layer': 'fileupload-pool',
'type': 'circle',
'paint': {
'circle-color': "#91b979",
'circle-radius': 7,
'circle-stroke-width': 2,
'circle-stroke-color': "#7aab5f"
}
});
map.addLayer({
"id": "service-area",
"source": "tegola-nidus",
"source-layer": "service-area-bounds",
"type": "line",
"paint": {
"line-color": "#f00"
}
});
});
const checkboxShowIssuesOnly = document.getElementById("showIssuesOnly");
checkboxShowIssuesOnly.onclick = handleShowIssuesOnly;
// Set the correct state if the browser remembers the state of the checkbox
handleShowIssuesOnly();
}
document.addEventListener('DOMContentLoaded', onLoad);
</script>
{{ end }}
{{ define "content" }}
<div class="container mt-4 results-container">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>Upload Results: {{ .C.Upload.Name }}</h2>
<span class="badge rounded-pill {{ .C.Upload.Status }}">
<i class="bi {{ .C.Upload.Status|iconUploadStatus }} me-1"></i
>{{ .C.Upload.Status|displayUploadStatus }}
</span>
</div>
<div class="row mb-4">
<div class="col-md-4">
<div class="card summary-card h-100 border-primary">
<div class="card-body text-center">
<h1 class="display-4 text-primary">
{{ .C.Upload.CountExisting }}
</h1>
<h5>Existing Pools</h5>
<p class="text-muted">Matches found in previous records</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card summary-card h-100 border-success">
<div class="card-body text-center">
<h1 class="display-4 text-success">{{ .C.Upload.CountNew }}</h1>
<h5>New Pools</h5>
<p class="text-muted">Not found in existing records</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card summary-card h-100 border-warning">
<div class="card-body text-center">
<h1 class="display-4 text-warning">{{ .C.Upload.CountOutside }}</h1>
<h5>Outside District</h5>
<p class="text-muted">Potential geocoding errors</p>
</div>
</div>
</div>
</div>
<div class="card mb-4">
<map-multipoint
id="map"
organization-id="{{ .Organization.ID }}"
tegola="{{ .URL.Tegola }}"
xmin="{{ .Organization.ServiceArea.Min.X }}"
ymin="{{ .Organization.ServiceArea.Min.Y }}"
xmax="{{ .Organization.ServiceArea.Max.X }}"
ymax="{{ .Organization.ServiceArea.Max.Y }}"
></map-multipoint>
</div>
<div class="card mb-4">
<div
class="card-header bg-light d-flex justify-content-between align-items-center"
>
<h5 class="mb-0">Data Preview</h5>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="showIssuesOnly" />
<label class="form-check-label" for="showIssuesOnly"
>Show issues only</label
>
</div>
</div>
<div class="card-body">
{{ range .C.Upload.Errors }}
<div class="alert alert-danger" role="alert">
<i class="bi bi-exclamation-triangle me-2"></i>
<strong>Error:</strong>{{ .Message }}
</div>
{{ end }}
{{ if eq .C.Upload.Status "uploaded" }}
<div class="alert alert-info" role="alert">
<i class="bi bi-exclamation-triangle me-2"></i>
<strong>Working:</strong> File is still processing... refresh this
page in a bit to see updates.
</div>
{{ else }}
{{ if eq (len .C.Upload.Pools) 0 }}
<div class="alert alert-warning" role="alert">
<i class="bi bi-exclamation-triangle me-2"></i>
<strong>Warning:</strong> No pools could be understood from your
file.
</div>
{{ else }}
<div class="table-responsive">
<table class="table table-hover table-striped">
<thead class="table-light">
<tr class="header">
<th></th>
<th>Street</th>
<th>City</th>
<th>Post</th>
<th>Status</th>
<th>Condition</th>
<th>Tags</th>
</tr>
</thead>
<tbody>
{{ range .C.Upload.Pools }}
<tr {{ if gt (len .Errors) 0 }}class="has-error"{{ end }}>
<td>
{{ if gt (len .Errors) 0 }}
<i
class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ range .Errors }}{{ .Message }}{{ end }}"
></i>
{{ end }}
</td>
<td>{{ .Street }}</td>
<td>{{ .Locality }}</td>
<td>{{ .PostalCode }}</td>
<td>
<span class="badge status {{ .Status }}"
>{{ .Status|title }}</span
>
</td>
<td>
<span class="badge condition {{ .Condition }}"
>{{ .Condition|title }}</span
>
</td>
<td>{{ len .Tags }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ end }}
{{ end }}
</div>
</div>
<div class="d-flex justify-content-between mt-4 mb-5">
<form action="{{ call .URL.Upload.Discard .C.CSVFileID }}" method="POST">
<button type="submit" class="btn btn-outline-danger">Discard</button>
</form>
<form action="{{ call .URL.Upload.Commit .C.CSVFileID }}" method="POST">
<button class="btn btn-primary" id="confirmUploadBtn">
<i class="bi bi-check2 me-1"></i> Confirm and Submit Data
</button>
</form>
</div>
</div>
{{ end }}