From cc3581aa4dfefa6dfc97986ba17e0e96c55d538a Mon Sep 17 00:00:00 2001 From: Ketan Patel Date: Sat, 4 Apr 2026 15:10:23 -0400 Subject: [PATCH] Adding the dashboard ups card fix --- app/routes/api_ups.py | 18 ++++++++++- app/static/js/dashboard.js | 58 ++++++++++++++++++++++-------------- app/templates/dashboard.html | 2 +- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/app/routes/api_ups.py b/app/routes/api_ups.py index b7719a7..8f96acc 100644 --- a/app/routes/api_ups.py +++ b/app/routes/api_ups.py @@ -297,7 +297,10 @@ async def ups_debug(ups_name: str, user=Depends(require_session)): async def get_ups_ui_tiles(ups_name: str, user=Depends(require_session)): r = get_redis() raw = r.get(f"ups:ui:tiles:{ups_name}") - default = {"types": {}, "order": [], "hidden": [], "custom": [], "positions": {}} + default = { + "types": {}, "order": [], "hidden": [], "custom": [], + "positions": {}, "card_size": None, + } if not raw: return default try: @@ -308,6 +311,7 @@ async def get_ups_ui_tiles(ups_name: str, user=Depends(require_session)): "hidden": data.get("hidden", []), "custom": data.get("custom", []), "positions": data.get("positions", {}), + "card_size": data.get("card_size"), } except Exception: return default @@ -322,6 +326,17 @@ async def save_ups_ui_tiles( hidden = payload.get("hidden") if isinstance(payload.get("hidden"), list) else [] custom = payload.get("custom") if isinstance(payload.get("custom"), list) else [] positions = payload.get("positions") if isinstance(payload.get("positions"), dict) else {} + raw_card_size = payload.get("card_size") + card_size = None + if isinstance(raw_card_size, dict): + try: + w = int(raw_card_size.get("width") or 0) + h = int(raw_card_size.get("height") or 0) + # Clamp to sane bounds matching the frontend resize limits + if 200 <= w <= 2000 and 200 <= h <= 2000: + card_size = {"width": w, "height": h} + except (TypeError, ValueError): + card_size = None norm_custom = [] for c in custom or []: if not isinstance(c, dict): @@ -342,6 +357,7 @@ async def save_ups_ui_tiles( "hidden": hidden, "custom": norm_custom, "positions": positions, + "card_size": card_size, "saved_ts": int(time.time()), } r = get_redis() diff --git a/app/static/js/dashboard.js b/app/static/js/dashboard.js index fa39201..b6254ce 100644 --- a/app/static/js/dashboard.js +++ b/app/static/js/dashboard.js @@ -163,8 +163,8 @@ async function loadServerTileConfig(name) { saveToStorage(TILE_TYPE_KEY, savedTileTypes); saveToStorage(CARD_SIZE_KEY, savedCardSizes); // Clear server layout - try { - await fetch(`/api/ups/${name}/ui_tiles`, { method:'DELETE' }); + try { + await window.apiFetch(`/api/ups/${name}/ui_tiles`, { method:'DELETE' }); debugLog(`Cleared server layout for ${name}`); } catch(err) { debugWarn(`Failed to clear server layout for ${name}:`, err); @@ -324,10 +324,11 @@ async function saveServerTileConfig(name) { id: c.id, metric: c.metric, chart: c.chart, source: c.source || 'live' })); const positions = savedTilePos[name] || {}; + const card_size = savedCardSizes[name] || null; try { - await fetch(`/api/ups/${name}/ui_tiles`, { - method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ types, order, hidden: hiddenArr, custom, positions }) + await window.apiFetch(`/api/ups/${name}/ui_tiles`, { + method: 'POST', + body: JSON.stringify({ types, order, hidden: hiddenArr, custom, positions, card_size }) }); } catch {} } @@ -369,6 +370,10 @@ function ensureUpsCard(name) { card.appendChild(handle); attachResizeBehavior(card, handle); } + // Restore saved card size if not already applied inline + if (!card.style.width && savedCardSizes[name]) { + restoreCardSize(name); + } return card; } const container = document.getElementById('ups-cards'); @@ -1261,7 +1266,7 @@ function persistTileOrder(name, grid) { function persistTilePositions(name, grid) { const positions = {}; let maxX = 0, maxY = 0; - + grid.querySelectorAll('.tile').forEach(tile => { const id = tile.dataset.tile; if (id) { @@ -1269,34 +1274,39 @@ function persistTilePositions(name, grid) { const top = parseInt(tile.style.top || '0', 10); const width = parseInt(tile.style.width || '0', 10) || tile.offsetWidth; const height = parseInt(tile.style.height || '0', 10) || tile.offsetHeight; - + positions[id] = { left, top, width, height }; - - // Calculate required card size + + // Track required card size (to grow card if tiles overflow) maxX = Math.max(maxX, left + width); maxY = Math.max(maxY, top + height); } }); - + savedTilePos[name] = positions; try { localStorage.setItem(TILE_POS_KEY, JSON.stringify(savedTilePos)); } catch(_) {} - - // Auto-adjust card size based on tile positions + + // Only grow the card if tiles overflow its current bounds. Never shrink + // the user's manually-sized card. if (maxX > 0 && maxY > 0) { - const cardWidth = Math.max(maxX + 20, 400); // 20px padding - const cardHeight = Math.max(maxY + 70, 300); // 70px for header + padding - persistCardSize(name, cardWidth, cardHeight); - - // Apply the size immediately const card = document.getElementById(`card-${name}`); if (card) { - card.style.width = `${cardWidth}px`; - card.style.height = `${cardHeight}px`; - grid.style.width = `${cardWidth - 20}px`; - grid.style.height = `${cardHeight - 70}px`; + const neededW = maxX + 20; // 20px right padding + const neededH = maxY + 70; // 70px for header + bottom padding + const currentW = card.offsetWidth; + const currentH = card.offsetHeight; + const newW = Math.max(currentW, neededW); + const newH = Math.max(currentH, neededH); + if (newW > currentW || newH > currentH) { + card.style.width = `${newW}px`; + card.style.height = `${newH}px`; + grid.style.width = `${newW - 20}px`; + grid.style.height = `${newH - 70}px`; + persistCardSize(name, newW, newH); + } } } - + scheduleServerTileSave(name); } @@ -1476,6 +1486,10 @@ document.addEventListener('DOMContentLoaded', () => { savedTileHidden[name] = hiddenSet; savedCustomTiles[name] = cfg.custom || []; savedTilePos[name] = cfg.positions || savedTilePos[name] || {}; + if (cfg.card_size && cfg.card_size.width && cfg.card_size.height) { + savedCardSizes[name] = { width: cfg.card_size.width, height: cfg.card_size.height }; + saveToStorage(CARD_SIZE_KEY, savedCardSizes); + } try { localStorage.setItem(TILE_TYPE_KEY, JSON.stringify(savedTileTypes)); } catch{} try { localStorage.setItem(TILE_ORDER_KEY, JSON.stringify(savedTileOrder)); } catch{} try { localStorage.setItem(TILE_HIDDEN_KEY, JSON.stringify(savedTileHidden)); } catch{} diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 5c8b919..0135f80 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -50,5 +50,5 @@ {% endblock %} {% block scripts %} - + {% endblock %}