diff --git a/server.py b/server.py index b20107b..50ccd5f 100644 --- a/server.py +++ b/server.py @@ -1065,6 +1065,7 @@ def list_assets( assigned_to: Optional[int] = Query(None), disney_park: Optional[str] = Query(None), disney_filter: Optional[str] = Query(None), + disney_group: Optional[str] = Query(None, description="Grouped park categories: park, resort, office, springs, other"), q: Optional[str] = Query(None), no_dex_days: Optional[int] = Query(None, ge=1), has_gps: Optional[bool] = Query(None), @@ -1092,6 +1093,19 @@ def list_assets( conditions.append("is_disney = 1") elif disney_filter == "non_disney": conditions.append("(is_disney IS NULL OR is_disney = 0)") + if disney_group: + park_groups = { + "park": ["magic-kingdom", "epcot", "hollywood-studios", "animal-kingdom"], + "resort": ["resort"], + "office": ["office"], + "springs": ["disney-springs"], + "other": ["other"], + } + parks = park_groups.get(disney_group) + if parks: + placeholders = ",".join("?" * len(parks)) + conditions.append(f"disney_park IN ({placeholders})") + params.extend(parks) if model: conditions.append("model = ?") params.append(model) diff --git a/static/index.html b/static/index.html index 69d7bed..66d093f 100644 --- a/static/index.html +++ b/static/index.html @@ -1340,7 +1340,13 @@
Disney Park
- + + + + + + + @@ -3899,6 +3911,15 @@ const PARK_ICONS = {'magic-kingdom':'🏰','epcot':'🌍','hollywood-studios':'🎬','animal-kingdom':'🌿','disney-springs':'🛍️','resort':'🏨','office':'🏢','other':'📍'}; const PARK_NAMES = {'magic-kingdom':'Magic Kingdom','epcot':'Epcot','hollywood-studios':'Hollywood Studios','animal-kingdom':'Animal Kingdom','disney-springs':'Disney Springs','resort':'Resort','office':'Office','other':'Other'}; + const PARK_GROUP_ICONS = {'park':'🏰','resort':'🏨','office':'🏢','springs':'🛍️','other':'📍'}; + const PARK_GROUP_NAMES = {'park':'Disney Park','resort':'Disney Resort','office':'Disney Office','springs':'Disney Springs','other':'Other Disney'}; + const PARK_GROUP_MAP = { + 'park': ['magic-kingdom','epcot','hollywood-studios','animal-kingdom'], + 'resort': ['resort'], + 'office': ['office'], + 'springs': ['disney-springs'], + 'other': ['other'], + }; function catLabel(cat) { const e = CATEGORY_MAP[cat]; return e && e.label ? e.label : (cat || 'Other'); @@ -4124,7 +4145,7 @@ } // ── Filter state ────────────────────────────────────────────────────── - let assetFilters = { category: null, status: null, make: null, disney_park: null, disney_filter: null, q: '', + let assetFilters = { category: null, status: null, make: null, disney_park: null, disney_group: null, disney_filter: null, q: '', customer_id: null, location_id: null, assigned_to: null, branch: null }; let noDexFilterActive = false; let assetOffset = 0; @@ -4222,10 +4243,23 @@ if (disneyFilterVal) { assetFilters.disney_filter = disneyFilterVal; assetFilters.disney_park = null; + assetFilters.disney_group = null; } else { var parkVal = parkEl.value; - assetFilters.disney_park = parkVal || null; - assetFilters.disney_filter = null; + if (parkVal && parkVal.startsWith('group:')) { + // Grouped park category + assetFilters.disney_group = parkVal.replace('group:', ''); + assetFilters.disney_park = null; + assetFilters.disney_filter = null; + } else if (parkVal) { + assetFilters.disney_park = parkVal; + assetFilters.disney_group = null; + assetFilters.disney_filter = null; + } else { + assetFilters.disney_park = null; + assetFilters.disney_group = null; + assetFilters.disney_filter = null; + } } assetFilters.customer_id = custEl.value || null; @@ -4266,6 +4300,7 @@ if (assetFilters.make) count++; if (assetFilters.disney_park) count++; + if (assetFilters.disney_group) count++; if (assetFilters.disney_filter) count++; if (assetFilters.customer_id) count++; if (assetFilters.location_id) count++; @@ -4292,6 +4327,7 @@ if (assetFilters.make) tags.push({key:'make', label:'\uD83C\uDFED ' + assetFilters.make}); if (assetFilters.disney_park) tags.push({key:'disney_park', label: parkIcon(assetFilters.disney_park) + ' ' + parkName(assetFilters.disney_park)}); + if (assetFilters.disney_group) tags.push({key:'disney_group', label: (PARK_GROUP_ICONS[assetFilters.disney_group] || '📍') + ' ' + (PARK_GROUP_NAMES[assetFilters.disney_group] || assetFilters.disney_group)}); if (assetFilters.disney_filter === 'disney') tags.push({key:'disney_filter', label:'🏰 Disney only'}); if (assetFilters.disney_filter === 'non_disney') tags.push({key:'disney_filter', label:'🏢 Non-Disney'}); if (assetFilters.customer_id) { @@ -4334,6 +4370,9 @@ } else if (key === 'disney_park') { document.getElementById('filterDisneyPark').value = ''; assetFilters.disney_park = null; + } else if (key === 'disney_group') { + document.getElementById('filterDisneyPark').value = ''; + assetFilters.disney_group = null; } else if (key === 'disney_filter') { document.getElementById('filterDisneyFilter').value = ''; assetFilters.disney_filter = null; @@ -4363,7 +4402,7 @@ } function clearAllFilters() { - assetFilters = { category: null, status: null, make: null, disney_park: null, disney_filter: null, q: '', + assetFilters = { category: null, status: null, make: null, disney_park: null, disney_group: null, disney_filter: null, q: '', customer_id: null, location_id: null, assigned_to: null, branch: null }; document.getElementById('assetSearch').value = ''; document.getElementById('clearSearch').style.display = 'none'; @@ -5001,6 +5040,7 @@ if (assetFilters.make) params.set('make', assetFilters.make); if (assetFilters.disney_park) params.set('disney_park', assetFilters.disney_park); + if (assetFilters.disney_group) params.set('disney_group', assetFilters.disney_group); if (assetFilters.disney_filter) params.set('disney_filter', assetFilters.disney_filter); if (assetFilters.q) params.set('q', assetFilters.q); if (assetFilters.customer_id) params.set('customer_id', assetFilters.customer_id); @@ -5069,16 +5109,17 @@ return parts.join(''); } - function setFilter(category, status, make, disney_park) { + function setFilter(category, status, make, disney_park, disney_group) { assetFilters.category = category; assetFilters.status = status; assetFilters.make = make; assetFilters.disney_park = disney_park; + assetFilters.disney_group = disney_group || null; assetFilters.disney_filter = null; // Sync dropdowns if (document.getElementById('filterCategory')) document.getElementById('filterCategory').value = category || ''; if (document.getElementById('filterMake')) document.getElementById('filterMake').value = make || ''; - if (document.getElementById('filterDisneyPark')) document.getElementById('filterDisneyPark').value = disney_park || ''; + if (document.getElementById('filterDisneyPark')) document.getElementById('filterDisneyPark').value = (disney_group ? 'group:' + disney_group : (disney_park || '')); renderActiveFilterTags(); assetOffset = 0; @@ -6069,7 +6110,7 @@ } // ── Map filter state ────────────────────────────────────────────────── - let mapFilters = { category: null, status: null, make: null, disney_park: null, disney_filter: null, q: '', + let mapFilters = { category: null, status: null, make: null, disney_park: null, disney_group: null, disney_filter: null, q: '', customer_id: null, location_id: null, assigned_to: null, branch: null }; let mapFilterDropdownsLoaded = false; let _mapFilterTimer; @@ -6128,10 +6169,22 @@ if (disneyFilterVal) { mapFilters.disney_filter = disneyFilterVal; mapFilters.disney_park = null; + mapFilters.disney_group = null; } else { var parkVal = document.getElementById('mapFilterDisneyPark').value; - mapFilters.disney_park = parkVal || null; - mapFilters.disney_filter = null; + if (parkVal && parkVal.startsWith('group:')) { + mapFilters.disney_group = parkVal.replace('group:', ''); + mapFilters.disney_park = null; + mapFilters.disney_filter = null; + } else if (parkVal) { + mapFilters.disney_park = parkVal; + mapFilters.disney_group = null; + mapFilters.disney_filter = null; + } else { + mapFilters.disney_park = null; + mapFilters.disney_group = null; + mapFilters.disney_filter = null; + } } mapFilters.customer_id = document.getElementById('mapFilterCustomer').value || null; @@ -6172,6 +6225,7 @@ if (mapFilters.category) count++; if (mapFilters.make) count++; if (mapFilters.disney_park) count++; + if (mapFilters.disney_group) count++; if (mapFilters.disney_filter) count++; if (mapFilters.customer_id) count++; if (mapFilters.location_id) count++; @@ -6196,6 +6250,7 @@ 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_group) tags.push({key:'disney_group', label: (PARK_GROUP_ICONS[mapFilters.disney_group] || '📍') + ' ' + (PARK_GROUP_NAMES[mapFilters.disney_group] || mapFilters.disney_group)}); 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) { @@ -6229,6 +6284,9 @@ } else if (key === 'disney_park') { document.getElementById('mapFilterDisneyPark').value = ''; mapFilters.disney_park = null; + } else if (key === 'disney_group') { + document.getElementById('mapFilterDisneyPark').value = ''; + mapFilters.disney_group = null; } else if (key === 'disney_filter') { document.getElementById('mapFilterDisneyFilter').value = ''; mapFilters.disney_filter = null; @@ -6253,7 +6311,7 @@ } function clearMapFilters() { - mapFilters = { category: null, status: null, make: null, disney_park: null, disney_filter: null, q: '', + mapFilters = { category: null, status: null, make: null, disney_park: null, disney_group: null, disney_filter: null, q: '', customer_id: null, location_id: null, assigned_to: null, branch: null }; document.getElementById('mapSearchInput').value = ''; document.getElementById('mapFilterCategory').value = ''; @@ -6310,7 +6368,11 @@ // 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 + // Disney park filter (individual or group) + if (mapFilters.disney_group) { + var groupParks = PARK_GROUP_MAP[mapFilters.disney_group] || []; + if (groupParks.indexOf(a.disney_park) === -1) return; + } if (mapFilters.disney_park && a.disney_park !== mapFilters.disney_park) return; // Text search if (q) {