Grayscale OSM base tiles, mobile-friendly dashboard and map with touch multi-select and box select, wider road click radius, and strip internal properties from JOSM export

This commit is contained in:
zyphlar
2026-10-15 12:44:48 -07:00
parent 7e5b3dc2ee
commit 9b8752eef5
6 changed files with 457 additions and 102 deletions
+127 -2
View File
@@ -346,6 +346,115 @@
color: #444;
font-style: italic;
}
/* ── Collapsible top menu (mobile) ── */
.topbar-menu {
flex: 1;
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
}
.topbar-spacer { flex: 1; }
.topbar-user { font-size: 11px; color: #888; }
.menu-toggle {
display: none;
margin-left: auto;
width: 40px;
height: 36px;
padding: 8px;
border: none;
border-radius: 5px;
background: #ffffff18;
cursor: pointer;
flex-direction: column;
justify-content: space-between;
}
.menu-toggle span {
display: block;
height: 2px;
border-radius: 1px;
background: #ddd;
}
@media (max-width: 768px) {
html, body { height: auto; }
.page { height: auto; min-height: 100%; }
.topbar {
flex-wrap: wrap;
position: sticky;
top: 0;
z-index: 10;
}
.menu-toggle { display: flex; }
.topbar-menu {
display: none;
flex-basis: 100%;
flex-direction: column;
align-items: stretch;
gap: 6px;
max-width: 560px;
margin: 0 auto;
padding: 4px 0 6px;
}
.topbar-menu.open { display: flex; }
.topbar-sep, .topbar-spacer { display: none; }
.topbar-menu .btn-topbar,
.topbar-menu form,
.topbar-menu form .btn-topbar {
display: block;
width: 100%;
padding: 10px 12px;
font-size: 14px;
text-align: left;
}
.topbar-user { padding: 4px 2px 0; font-size: 12px; }
.main {
flex-direction: column;
overflow: visible;
}
.left {
width: 100%;
max-width: 560px;
margin: 0 auto;
border-right: none;
overflow: visible;
}
.workflows { overflow: visible; padding: 12px; }
.county-tab { padding: 12px; font-size: 14px; }
.step { flex-wrap: wrap; padding: 10px 12px; }
.step-label { font-size: 13px; min-width: 120px; }
.step-actions { margin-left: auto; flex-wrap: wrap; justify-content: flex-end; }
.btn-run { padding: 8px 16px; font-size: 13px; }
.upload-input { width: 100%; max-width: 200px; }
.files-strip { max-height: 160px; overflow-y: auto; }
.right {
min-height: 60vh;
border-top: 1px solid #d8dbe0;
}
}
</style>
</head>
<body>
@@ -354,10 +463,14 @@
<!-- Top bar -->
<div class="topbar">
<h1>OSM Import Tools</h1>
<button class="menu-toggle" id="menuToggle" aria-label="Toggle menu" aria-expanded="false" aria-controls="topbarMenu">
<span></span><span></span><span></span>
</button>
<div class="topbar-menu" id="topbarMenu">
<div class="topbar-sep"></div>
<button class="btn-topbar" onclick="runScript('ls', '')">List Files</button>
<button class="btn-topbar" onclick="clearData()" style="color:#f88;">Clear Data</button>
<div style="flex:1"></div>
<div class="topbar-spacer"></div>
<a href="/counties" class="btn-topbar">Counties</a>
<a href="/exceptions" class="btn-topbar">Street Exceptions</a>
<a href="/exclusions" class="btn-topbar">Exclusions</a>
@@ -366,13 +479,14 @@
<a href="/map" class="btn-topbar purple">Open Map Viewer</a>
<div class="topbar-sep"></div>
{% if current_user %}
<span style="font-size:11px;color:#888;">{{ current_user }}</span>
<span class="topbar-user">{{ current_user }}</span>
<form method="POST" action="/logout" style="display:inline;margin:0">
<button type="submit" class="btn-topbar">Logout</button>
</form>
{% else %}
<a href="/login" class="btn-topbar" style="color:#f0a830;">Login</a>
{% endif %}
</div><!-- /topbar-menu -->
</div>
<div class="main">
@@ -611,6 +725,13 @@
});
}
// Mobile top menu toggle
document.getElementById('menuToggle').addEventListener('click', function() {
const menu = document.getElementById('topbarMenu');
const open = menu.classList.toggle('open');
this.setAttribute('aria-expanded', open ? 'true' : 'false');
});
// Init
if (activeCounty) selectCounty(activeCounty);
@@ -622,6 +743,10 @@
showStatus(`Running: ${scriptName} (${activeCounty})`, 'info');
disableButtons();
document.getElementById('cancelButton').classList.add('active');
// On narrow screens the console is below the steps; bring it into view
if (window.matchMedia('(max-width: 768px)').matches) {
document.querySelector('.right').scrollIntoView({ behavior: 'smooth', block: 'start' });
}
let forceDownload = false;
if (scriptName === 'diff-addresses') {