chore: remove accidentally committed gps backup file
This commit is contained in:
+351
-57
@@ -827,16 +827,6 @@
|
||||
.map-search-row input {
|
||||
flex: 1; min-width: 0;
|
||||
}
|
||||
.map-filter-chips {
|
||||
display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 6px;
|
||||
}
|
||||
.map-filter-chip {
|
||||
font-size: 10px; font-weight: 600; padding: 3px 8px;
|
||||
border-radius: 12px; border: 1px solid var(--border);
|
||||
background: var(--card2); color: var(--text2); cursor: pointer;
|
||||
transition: all 0.12s;
|
||||
}
|
||||
.map-filter-chip.active { background: var(--accent); border-color: var(--accent); color: #fff; }
|
||||
|
||||
/* Asset list below map */
|
||||
.map-asset-list {
|
||||
@@ -1281,6 +1271,22 @@
|
||||
<div id="detailFields"></div>
|
||||
</div>
|
||||
|
||||
<!-- Photo card -->
|
||||
<div class="card" id="detailPhotoCard" style="display:none;">
|
||||
<div class="card-title">📷 Photo</div>
|
||||
<div style="margin-top:8px;text-align:center;">
|
||||
<img id="detailPhotoImg" style="max-width:100%;max-height:60vh;border-radius:8px;cursor:pointer;"
|
||||
onclick="openPhotoModal()" alt="Asset photo">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Photo modal (fullscreen) -->
|
||||
<div id="photoModal" style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);z-index:9999;cursor:pointer;justify-content:center;align-items:center;"
|
||||
onclick="closePhotoModal(event)">
|
||||
<img id="photoModalImg" style="max-width:95%;max-height:95%;border-radius:4px;object-fit:contain;">
|
||||
<span style="position:absolute;top:16px;right:24px;color:#fff;font-size:32px;font-weight:bold;cursor:pointer;" onclick="closePhotoModal()">✕</span>
|
||||
</div>
|
||||
|
||||
<!-- Directions card -->
|
||||
<div class="card" id="detailDirections" style="display:none;">
|
||||
<div class="card-title">📍 Directions & Access</div>
|
||||
@@ -1378,8 +1384,86 @@
|
||||
oninput="mapDebounceFilter()">
|
||||
<button class="btn btn-secondary btn-sm" onclick="document.getElementById('mapSearchInput').value='';mapDebounceFilter()" style="white-space:nowrap;">✕</button>
|
||||
</div>
|
||||
<!-- Filter chips -->
|
||||
<div class="map-filter-chips" id="mapFilterChips"></div>
|
||||
<!-- Filter toggle + panel (same pattern as assets tab) -->
|
||||
<div style="display:flex;gap:6px;align-items:flex-start;margin-bottom:8px;">
|
||||
<button class="filter-toggle" id="mapFilterToggle" onclick="toggleMapFilterPanel()" title="Toggle filter panel">
|
||||
🎯 Filters <span id="mapFilterCount" class="ft-count" style="display:none;">0</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="filter-panel" id="mapFilterPanel">
|
||||
<div class="fp-row">
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Category</div>
|
||||
<select id="mapFilterCategory" class="input-field" onchange="onMapFilterChange()">
|
||||
<option value="">All categories</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Make</div>
|
||||
<select id="mapFilterMake" class="input-field" onchange="onMapFilterChange()">
|
||||
<option value="">All makes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fp-row">
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Location Type</div>
|
||||
<select id="mapFilterDisneyFilter" class="input-field" onchange="onMapFilterChange()">
|
||||
<option value="">All locations</option>
|
||||
<option value="disney">🏰 Disney</option>
|
||||
<option value="non_disney">🏢 Non-Disney</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Disney Park</div>
|
||||
<select id="mapFilterDisneyPark" class="input-field" onchange="onMapFilterChange()">
|
||||
<option value="">All parks</option>
|
||||
<option disabled>──────────</option>
|
||||
<option value="magic-kingdom">🏰 Magic Kingdom</option>
|
||||
<option value="epcot">🌍 Epcot</option>
|
||||
<option value="hollywood-studios">🎬 Hollywood Studios</option>
|
||||
<option value="animal-kingdom">🌿 Animal Kingdom</option>
|
||||
<option value="disney-springs">🛍️ Disney Springs</option>
|
||||
<option value="resort">🏨 Resort</option>
|
||||
<option value="office">🏢 Office</option>
|
||||
<option value="other">📍 Other</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fp-row">
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Customer</div>
|
||||
<select id="mapFilterCustomer" class="input-field" onchange="onMapFilterChange()">
|
||||
<option value="">All customers</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Location</div>
|
||||
<select id="mapFilterLocation" class="input-field" onchange="onMapFilterChange()" disabled>
|
||||
<option value="">All locations</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fp-row">
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Branch</div>
|
||||
<select id="mapFilterBranch" class="input-field" onchange="onMapFilterChange()">
|
||||
<option value="">All branches</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="flex:1">
|
||||
<div class="fp-label">Assigned To</div>
|
||||
<select id="mapFilterAssignedTo" class="input-field" onchange="onMapFilterChange()">
|
||||
<option value="">Anyone</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fp-actions">
|
||||
<button class="btn btn-outline btn-xs" onclick="clearMapFilters()" style="flex:1;">✕ Clear all filters</button>
|
||||
<button class="btn btn-outline btn-xs" onclick="toggleMapFilterPanel()" style="flex:1;">✓ Done</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="active-filters" id="mapActiveFilters"></div>
|
||||
<!-- Map -->
|
||||
<div id="mapContainer"></div>
|
||||
<!-- Asset list -->
|
||||
@@ -3831,6 +3915,18 @@
|
||||
df('Created', formatDate(a.created_at)) +
|
||||
df('Updated', formatDate(a.updated_at));
|
||||
|
||||
// Photo
|
||||
const photoCard = document.getElementById('detailPhotoCard');
|
||||
const photoImg = document.getElementById('detailPhotoImg');
|
||||
if (a.photo_path) {
|
||||
photoCard.style.display = 'block';
|
||||
photoImg.src = a.photo_path;
|
||||
photoImg.onload = () => { photoImg.style.display = 'inline'; };
|
||||
photoImg.onerror = () => { photoCard.style.display = 'none'; };
|
||||
} else {
|
||||
photoCard.style.display = 'none';
|
||||
}
|
||||
|
||||
// Location / Directions
|
||||
const hasDir = a.address || a.building_name || a.building_number || a.floor || a.room || a.trailer_number || a.walking_directions || a.map_link || a.parking_location;
|
||||
const dirCard = document.getElementById('detailDirections');
|
||||
@@ -4016,6 +4112,34 @@
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
// ── Photo viewer ──────────────────────────────────────────────────
|
||||
function openPhotoModal() {
|
||||
const img = document.getElementById('detailPhotoImg');
|
||||
const modal = document.getElementById('photoModal');
|
||||
const modalImg = document.getElementById('photoModalImg');
|
||||
if (!img || !modal || !modalImg) return;
|
||||
modalImg.src = img.src;
|
||||
modal.style.display = 'flex';
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
function closePhotoModal(event) {
|
||||
if (event && event.target && event.target.id !== 'photoModal' && event.target.id !== 'photoModalImg' && event.target.tagName !== 'SPAN') return;
|
||||
const modal = document.getElementById('photoModal');
|
||||
if (modal) {
|
||||
modal.style.display = 'none';
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
}
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
const modal = document.getElementById('photoModal');
|
||||
if (modal && modal.style.display === 'flex') {
|
||||
modal.style.display = 'none';
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function navigateToAsset(mode) {
|
||||
mode = mode || 'driving';
|
||||
if (!AppState.currentAssetId) {
|
||||
@@ -4497,81 +4621,252 @@
|
||||
}
|
||||
|
||||
|
||||
// ── Map filter state ──────────────────────────────────────────────────
|
||||
let mapFilters = { category: null, status: null, make: null, disney_park: null, disney_filter: null, q: '',
|
||||
customer_id: null, location_id: null, assigned_to: null, branch: null };
|
||||
let mapFilterDropdownsLoaded = false;
|
||||
|
||||
function toggleMapFilterPanel() {
|
||||
const panel = document.getElementById('mapFilterPanel');
|
||||
const toggle = document.getElementById('mapFilterToggle');
|
||||
panel.classList.toggle('open');
|
||||
toggle.classList.toggle('active', panel.classList.contains('open'));
|
||||
if (panel.classList.contains('open') && !mapFilterDropdownsLoaded) {
|
||||
loadMapFilterDropdowns();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMapFilterDropdowns() {
|
||||
if (mapFilterDropdownsLoaded) return;
|
||||
mapFilterDropdownsLoaded = true;
|
||||
var panel = document.getElementById('mapFilterPanel');
|
||||
var loadingMsg = document.createElement('div');
|
||||
loadingMsg.className = 'loading-spinner';
|
||||
loadingMsg.innerHTML = '<span class="spinner"></span> Loading filters...';
|
||||
panel.appendChild(loadingMsg);
|
||||
try {
|
||||
var cats = await api('/api/categories');
|
||||
document.getElementById('mapFilterCategory').innerHTML = '<option value="">All categories</option>' +
|
||||
cats.map(function(c) { return '<option value="' + esc(c) + '">' + esc(c) + '</option>'; }).join('');
|
||||
|
||||
var makes = await api('/api/makes');
|
||||
document.getElementById('mapFilterMake').innerHTML = '<option value="">All makes</option>' +
|
||||
makes.map(function(m) { return '<option value="' + esc(m) + '">' + esc(m) + '</option>'; }).join('');
|
||||
|
||||
var customers = await api('/api/customers');
|
||||
document.getElementById('mapFilterCustomer').innerHTML = '<option value="">All customers</option>' +
|
||||
customers.map(function(c) { return '<option value="' + c.id + '">' + esc(c.name) + '</option>'; }).join('');
|
||||
|
||||
var users = await api('/api/users');
|
||||
document.getElementById('mapFilterAssignedTo').innerHTML = '<option value="">Anyone</option>' +
|
||||
users.filter(function(u) { return u.role === 'technician' || u.role === 'admin'; })
|
||||
.map(function(u) { return '<option value="' + esc(u.username) + '">' + esc(u.username) + '</option>'; }).join('');
|
||||
|
||||
var branches = await api('/api/branches');
|
||||
document.getElementById('mapFilterBranch').innerHTML = '<option value="">All branches</option>' +
|
||||
branches.branches.map(function(b) { return '<option value="' + esc(b.name) + '">' + esc(b.name) + ' (' + b.machine_count + ')</option>'; }).join('');
|
||||
} catch (e) {
|
||||
showToast('Failed to load filter options', true);
|
||||
} finally {
|
||||
if (loadingMsg && loadingMsg.parentNode) loadingMsg.parentNode.removeChild(loadingMsg);
|
||||
}
|
||||
}
|
||||
|
||||
function onMapFilterChange() {
|
||||
mapFilters.category = document.getElementById('mapFilterCategory').value || null;
|
||||
mapFilters.make = document.getElementById('mapFilterMake').value || null;
|
||||
|
||||
var disneyFilterVal = document.getElementById('mapFilterDisneyFilter').value;
|
||||
if (disneyFilterVal) {
|
||||
mapFilters.disney_filter = disneyFilterVal;
|
||||
mapFilters.disney_park = null;
|
||||
} else {
|
||||
var parkVal = document.getElementById('mapFilterDisneyPark').value;
|
||||
mapFilters.disney_park = parkVal || null;
|
||||
mapFilters.disney_filter = null;
|
||||
}
|
||||
mapFilters.customer_id = document.getElementById('mapFilterCustomer').value || null;
|
||||
|
||||
var locEl = document.getElementById('mapFilterLocation');
|
||||
var prevCust = locEl.dataset.customerId;
|
||||
var custEl = document.getElementById('mapFilterCustomer');
|
||||
if (custEl.value !== prevCust) {
|
||||
locEl.innerHTML = '<option value="">All locations</option>';
|
||||
locEl.disabled = true;
|
||||
mapFilters.location_id = null;
|
||||
if (custEl.value) {
|
||||
loadMapLocationsForCustomer(custEl.value);
|
||||
}
|
||||
} else {
|
||||
mapFilters.location_id = locEl.value || null;
|
||||
}
|
||||
locEl.dataset.customerId = custEl.value;
|
||||
|
||||
mapFilters.assigned_to = document.getElementById('mapFilterAssignedTo').value || null;
|
||||
mapFilters.branch = document.getElementById('mapFilterBranch').value || null;
|
||||
|
||||
renderMapActiveFilterTags();
|
||||
applyMapFilter();
|
||||
}
|
||||
|
||||
async function loadMapLocationsForCustomer(customerId) {
|
||||
try {
|
||||
var locations = await api('/api/locations?customer_id=' + customerId);
|
||||
var locEl = document.getElementById('mapFilterLocation');
|
||||
locEl.innerHTML = '<option value="">All locations</option>' +
|
||||
locations.map(function(l) { return '<option value="' + l.id + '">' + esc(l.name) + '</option>'; }).join('');
|
||||
locEl.disabled = false;
|
||||
} catch (e) { showToast('Failed to load locations', true); }
|
||||
}
|
||||
|
||||
function getMapActiveFilterCount() {
|
||||
var count = 0;
|
||||
if (mapFilters.category) count++;
|
||||
if (mapFilters.make) count++;
|
||||
if (mapFilters.disney_park) count++;
|
||||
if (mapFilters.disney_filter) count++;
|
||||
if (mapFilters.customer_id) count++;
|
||||
if (mapFilters.location_id) count++;
|
||||
if (mapFilters.assigned_to) count++;
|
||||
if (mapFilters.branch) count++;
|
||||
if (mapFilters.q) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
function renderMapActiveFilterTags() {
|
||||
var el = document.getElementById('mapActiveFilters');
|
||||
var countEl = document.getElementById('mapFilterCount');
|
||||
var toggle = document.getElementById('mapFilterToggle');
|
||||
var count = getMapActiveFilterCount();
|
||||
|
||||
countEl.textContent = count;
|
||||
countEl.style.display = count > 0 ? 'inline' : 'none';
|
||||
if (toggle) toggle.classList.toggle('active', count > 0);
|
||||
|
||||
var tags = [];
|
||||
if (mapFilters.q) tags.push({key:'q', label:'🔍 "' + mapFilters.q + '"'});
|
||||
if (mapFilters.category) tags.push({key:'category', label:'📂 ' + mapFilters.category});
|
||||
if (mapFilters.make) tags.push({key:'make', label:'🏭 ' + mapFilters.make});
|
||||
if (mapFilters.disney_park) tags.push({key:'disney_park', label: parkIcon(mapFilters.disney_park) + ' ' + parkName(mapFilters.disney_park)});
|
||||
if (mapFilters.disney_filter === 'disney') tags.push({key:'disney_filter', label:'🏰 Disney only'});
|
||||
if (mapFilters.disney_filter === 'non_disney') tags.push({key:'disney_filter', label:'🏢 Non-Disney'});
|
||||
if (mapFilters.customer_id) {
|
||||
var custSel = document.getElementById('mapFilterCustomer');
|
||||
var txt = custSel.options[custSel.selectedIndex] ? custSel.options[custSel.selectedIndex].text : 'Customer';
|
||||
tags.push({key:'customer_id', label:'🟢 ' + txt});
|
||||
}
|
||||
if (mapFilters.location_id) {
|
||||
var locSel = document.getElementById('mapFilterLocation');
|
||||
var txt = locSel.options[locSel.selectedIndex] ? locSel.options[locSel.selectedIndex].text : 'Location';
|
||||
tags.push({key:'location_id', label:'📍 ' + txt});
|
||||
}
|
||||
if (mapFilters.assigned_to) tags.push({key:'assigned_to', label:'👤 ' + mapFilters.assigned_to});
|
||||
if (mapFilters.branch) tags.push({key:'branch', label:'🏢 ' + mapFilters.branch});
|
||||
|
||||
el.innerHTML = tags.map(function(t) {
|
||||
return '<span class="filter-tag">' + esc(t.label) + ' <span class="ft-remove" onclick="removeMapFilter(\'' + t.key + '\')">✕</span></span>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function removeMapFilter(key) {
|
||||
if (key === 'q') {
|
||||
document.getElementById('mapSearchInput').value = '';
|
||||
mapFilters.q = '';
|
||||
} else if (key === 'category') {
|
||||
document.getElementById('mapFilterCategory').value = '';
|
||||
mapFilters.category = null;
|
||||
} else if (key === 'make') {
|
||||
document.getElementById('mapFilterMake').value = '';
|
||||
mapFilters.make = null;
|
||||
} else if (key === 'disney_park') {
|
||||
document.getElementById('mapFilterDisneyPark').value = '';
|
||||
mapFilters.disney_park = null;
|
||||
} else if (key === 'disney_filter') {
|
||||
document.getElementById('mapFilterDisneyFilter').value = '';
|
||||
mapFilters.disney_filter = null;
|
||||
} else if (key === 'customer_id') {
|
||||
document.getElementById('mapFilterCustomer').value = '';
|
||||
document.getElementById('mapFilterLocation').innerHTML = '<option value="">All locations</option>';
|
||||
document.getElementById('mapFilterLocation').disabled = true;
|
||||
mapFilters.customer_id = null;
|
||||
mapFilters.location_id = null;
|
||||
} else if (key === 'location_id') {
|
||||
document.getElementById('mapFilterLocation').value = '';
|
||||
mapFilters.location_id = null;
|
||||
} else if (key === 'assigned_to') {
|
||||
document.getElementById('mapFilterAssignedTo').value = '';
|
||||
mapFilters.assigned_to = null;
|
||||
} else if (key === 'branch') {
|
||||
document.getElementById('mapFilterBranch').value = '';
|
||||
mapFilters.branch = null;
|
||||
}
|
||||
renderMapActiveFilterTags();
|
||||
applyMapFilter();
|
||||
}
|
||||
|
||||
function clearMapFilters() {
|
||||
mapFilters = { category: null, status: null, make: null, disney_park: null, disney_filter: null, q: '',
|
||||
customer_id: null, location_id: null, assigned_to: null, branch: null };
|
||||
document.getElementById('mapSearchInput').value = '';
|
||||
document.getElementById('mapFilterCategory').value = '';
|
||||
document.getElementById('mapFilterMake').value = '';
|
||||
document.getElementById('mapFilterDisneyPark').value = '';
|
||||
document.getElementById('mapFilterDisneyFilter').value = '';
|
||||
document.getElementById('mapFilterCustomer').value = '';
|
||||
document.getElementById('mapFilterLocation').innerHTML = '<option value="">All locations</option>';
|
||||
document.getElementById('mapFilterLocation').disabled = true;
|
||||
document.getElementById('mapFilterAssignedTo').value = '';
|
||||
document.getElementById('mapFilterBranch').value = '';
|
||||
renderMapActiveFilterTags();
|
||||
applyMapFilter();
|
||||
}
|
||||
|
||||
async function loadAssetPins() {
|
||||
// Store markers on a namespace so we can clear them
|
||||
if (!window._assetPins) window._assetPins = [];
|
||||
// Clear existing markers
|
||||
window._assetPins.forEach(function(m) { if (map) map.removeLayer(m); });
|
||||
window._assetPins = [];
|
||||
|
||||
try {
|
||||
const assets = await api('/api/assets?has_gps=true&limit=2000');
|
||||
_mapAllAssets = assets;
|
||||
buildMapFilterChips(assets);
|
||||
// Apply current filter
|
||||
applyMapFilter();
|
||||
} catch (e) {
|
||||
console.error('Failed to load asset pins:', e);
|
||||
showToast('Failed to load map assets — ' + (e.message || 'connection error'), true);
|
||||
}
|
||||
}
|
||||
|
||||
function buildMapFilterChips(assets) {
|
||||
var cats = {}; var statuses = {};
|
||||
assets.forEach(function(a) {
|
||||
if (a.category) cats[a.category] = (cats[a.category] || 0) + 1;
|
||||
if (a.status) statuses[a.status] = (statuses[a.status] || 0) + 1;
|
||||
});
|
||||
var catKeys = Object.keys(cats).sort();
|
||||
var statusKeys = Object.keys(statuses).sort();
|
||||
var html = '';
|
||||
html += '<span class="map-filter-chip' + (!_mapActiveCategory ? ' active' : '') + '" onclick="mapSetCategory(\'\')">All</span>';
|
||||
catKeys.forEach(function(c) {
|
||||
html += '<span class="map-filter-chip' + (_mapActiveCategory === c ? ' active' : '') + '" onclick="mapSetCategory(\'' + c.replace(/'/g, "\\'") + '\')">' + esc(c) + ' (' + cats[c] + ')</span>';
|
||||
});
|
||||
html += '<span class="map-filter-chip' + (!_mapActiveStatus ? ' active' : '') + '" onclick="mapSetStatus(\'\')">All Status</span>';
|
||||
statusKeys.forEach(function(s) {
|
||||
html += '<span class="map-filter-chip' + (_mapActiveStatus === s ? ' active' : '') + '" onclick="mapSetStatus(\'' + s.replace(/'/g, "\\'") + '\')">' + esc(s) + '</span>';
|
||||
});
|
||||
document.getElementById('mapFilterChips').innerHTML = html;
|
||||
}
|
||||
|
||||
function mapSetCategory(cat) {
|
||||
_mapActiveCategory = _mapActiveCategory === cat ? '' : cat;
|
||||
_mapActiveStatus = '';
|
||||
applyMapFilter();
|
||||
buildMapFilterChips(_mapAllAssets);
|
||||
}
|
||||
|
||||
function mapSetStatus(status) {
|
||||
_mapActiveStatus = _mapActiveStatus === status ? '' : status;
|
||||
_mapActiveCategory = '';
|
||||
applyMapFilter();
|
||||
buildMapFilterChips(_mapAllAssets);
|
||||
}
|
||||
|
||||
function mapDebounceFilter() {
|
||||
if (_mapFilterTimer) clearTimeout(_mapFilterTimer);
|
||||
mapFilters.q = (document.getElementById('mapSearchInput').value || '').toLowerCase().trim();
|
||||
renderMapActiveFilterTags();
|
||||
_mapFilterTimer = setTimeout(applyMapFilter, 200);
|
||||
}
|
||||
|
||||
function applyMapFilter() {
|
||||
if (_mapFilterTimer) { clearTimeout(_mapFilterTimer); _mapFilterTimer = null; }
|
||||
|
||||
var q = (document.getElementById('mapSearchInput').value || '').toLowerCase().trim();
|
||||
var q = mapFilters.q;
|
||||
|
||||
// Clear existing pins
|
||||
window._assetPins.forEach(function(m) { if (map) map.removeLayer(m); });
|
||||
window._assetPins = [];
|
||||
|
||||
var matched = [];
|
||||
_mapAllAssets.forEach(function(a) {
|
||||
var allAssets = _mapAllAssets || [];
|
||||
allAssets.forEach(function(a) {
|
||||
// Category filter
|
||||
if (_mapActiveCategory && a.category !== _mapActiveCategory) return;
|
||||
// Status filter
|
||||
if (_mapActiveStatus && a.status !== _mapActiveStatus) return;
|
||||
if (mapFilters.category && a.category !== mapFilters.category) return;
|
||||
// Make filter
|
||||
if (mapFilters.make && a.make !== mapFilters.make) return;
|
||||
// Disney/non-disney filter
|
||||
if (mapFilters.disney_filter === 'disney' && !a.is_disney) return;
|
||||
if (mapFilters.disney_filter === 'non_disney' && a.is_disney) return;
|
||||
// Disney park filter
|
||||
if (mapFilters.disney_park && a.disney_park !== mapFilters.disney_park) return;
|
||||
// Text search
|
||||
if (q) {
|
||||
var haystack = ((a.name || '') + ' ' + (a.machine_id || '') + ' ' + (a.category || '') + ' ' + (a.description || '')).toLowerCase();
|
||||
var haystack = ((a.name || '') + ' ' + (a.machine_id || '') + ' ' + (a.category || '') + ' ' + (a.company || '') + ' ' + (a.description || '')).toLowerCase();
|
||||
if (haystack.indexOf(q) === -1) return;
|
||||
}
|
||||
matched.push(a);
|
||||
@@ -4619,7 +4914,6 @@
|
||||
el.innerHTML = '<div class="map-asset-empty">📦 No assets match your search</div>';
|
||||
return;
|
||||
}
|
||||
// Sort by name
|
||||
var sorted = assets.slice().sort(function(a, b) { return (a.name || '').localeCompare(b.name || ''); });
|
||||
var html = '';
|
||||
sorted.forEach(function(a) {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
// Caches app shell + CDN deps. Network-first for API, cache fallback for static.
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const CACHE_NAME = 'canteen-v6';
|
||||
const CACHE_NAME = 'canteen-v7';
|
||||
|
||||
// App shell — core resources needed to boot the PWA
|
||||
const APP_SHELL = [
|
||||
|
||||
@@ -142,8 +142,8 @@ class TestGPSControls:
|
||||
assert "GPS location not available" in body()
|
||||
|
||||
def test_pins_chip_ui(self):
|
||||
"""Pin toggle chip exists."""
|
||||
assert "chipPins" in body()
|
||||
"""🎯 Filters toggle button exists in map tab."""
|
||||
assert "mapFilterToggle" in body()
|
||||
|
||||
|
||||
class TestHeatmap:
|
||||
|
||||
Reference in New Issue
Block a user