nidus-sync/sync/template/district.html
Eli Ribble b91718cd7c
Color districts by regionid
The colors jump as you zoom, but they still technically work, so I'm
committing it.
2026-01-14 15:52:14 +00:00

185 lines
4.8 KiB
HTML

{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "extraheader"}}
<script src='https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.css' rel='stylesheet' />
<script src="/static/js/geocode.js"></script>
<script src="/static/js/location.js"></script>
<script src="/static/js/map.js"></script>
<script>
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
function setDistrictColors(map) {
const features = map.querySourceFeatures('tegola-mosquito', {sourceLayer: 'district'});
console.log("features", features);
const regionIds = [...new Set(features.map(f => f.properties.regionid))];
map.setPaintProperty('districts', 'fill-opacity', 0.4);
if (regionIds.length > 0) {
// Generate color mapping
const colorScale = {};
regionIds.forEach((id, index) => {
// Generate a color (this is a simple example - consider using a proper color library)
colorScale[id] = `hsl(${index * (360 / regionIds.length)}, 70%, 50%)`;
});
const matchExpression = ['match', ['get', 'regionid']];
regionIds.forEach(id => {
matchExpression.push(id, colorScale[id]);
});
matchExpression.push('#cccccc'); // Default color
console.log("using district coloring", matchExpression);
map.setPaintProperty('districts', 'fill-color', matchExpression);
} else {
map.setPaintProperty('districts', 'fill-color', 'rgb(250, 100, 100)');
console.log("using fallback district coloring");
}
}
function onLoad() {
console.log("Setting up the map...");
mapboxgl.accessToken = MAPBOX_ACCESS_TOKEN;
const map = new mapboxgl.Map({
container: 'map', // container ID
style: 'mapbox://styles/mapbox/standard', // style URL
//style: 'mapbox://styles/eliribble/cmke4af8i004401suh3cahegw',
center: [-119.3, 36.327], // starting position [lng, lat]
//center: [7.01, 50.74],
zoom: 9 // starting zoom
});
map.on("load", function() {
console.log("Map post-load...");
map.addSource('tegola-mosquito', {
'type': 'vector',
'tiles': [
'https://dev-tegola.nidus.cloud/maps/mosquito/{z}/{x}/{y}'
]
});
map.addLayer({
'id': 'districts',
'source': 'tegola-mosquito', // ID of the tile source created above
'source-layer': 'district',
'type': 'fill',
});
map.addInteraction("nidus-click-interaction", {
type: 'click',
target: { layerId: 'mosquito' },
handler: (e) => {
const coordinates = e.feature.geometry.coordinates.slice();
const properties = e.feature.properties;
console.log("Coordinates", coordinates[0]);
console.log("Properties", properties);
/*new mapboxgl.Popup()
.setLngLat(coordinates[0][0])
.setHTML("Cell: " + properties.cell)
.addTo(map);*/
//window.location.href = '/cell/' + properties.cell;
}
});
map.addInteraction('nidus-mouseenter-interaction', {
type: 'mouseenter',
target: { layerId: 'nidus' },
handler: () => {
map.getCanvas().style.cursor = 'pointer';
}
});
map.addInteraction('nidus-mouseleave-interaction', {
type: 'mouseleave',
target: { layerId: 'nidus' },
handler: () => {
map.getCanvas().style.cursor = '';
}
});
map.on('sourcedata', (e) => {
console.log("source loaded", e);
if (e.sourceId == 'tegola-mosquito' && e.isSourceLoaded) {
setDistrictColors(map)
}
});
console.log("Map post-load done.");
});
map.addControl(new mapboxgl.NavigationControl());
console.log("Map init done.");
}
document.addEventListener("DOMContentLoaded", onLoad);
</script>
<style>
body {
background-color: #f8f9fa;
}
.dashboard-container {
padding: 20px 0;
}
.stats-card {
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
transition: transform 0.2s;
height: 100%;
}
.stats-card:hover {
transform: translateY(-5px);
}
.map-container {
background-color: #e9ecef;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
height: 500px;
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
}
#map {
height: 500px;
width:100%;
margin-bottom: 10px;
}
#map img {
max-width: none;
min-width: 0px;
height: auto;
}
.section-title {
margin: 30px 0 20px;
padding-bottom: 10px;
border-bottom: 1px solid #dee2e6;
}
.last-refreshed {
color: #6c757d;
}
.logo-placeholder {
width: 100px;
height: 40px;
background-color: #e9ecef;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
}
.metric-icon {
font-size: 2rem;
margin-bottom: 10px;
display: inline-block;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
border-radius: 50%;
}
.metric-value {
font-size: 2rem;
font-weight: bold;
}
.syncing {
color: #28a745;
animation: fa-spin 2s linear infinite;
}
</style>
{{end}}
{{define "content"}}
<div class="container my-4">
<div class="card-body p-0">
<div class="map-container" id="map-container">
<div id="map"></div>
</div>
</div>
</div>
{{end}}