From 84d23ffa38649daaa5f2b3b08e59dd569eba4c63 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 00:16:30 +0000 Subject: [PATCH 1/2] Initial plan From 2d7ea6469aff786c9d6d144b0c5fa97f36f5af9a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 00:21:14 +0000 Subject: [PATCH 2/2] Add system map page with interactive network graph visualization Co-authored-by: HeadyConnection <250789142+HeadyConnection@users.noreply.github.com> --- .../apps/heady_admin_ui/css/system-map.css | 611 ++++++++++++++ .../apps/heady_admin_ui/index.html | 4 + .../apps/heady_admin_ui/js/network-graph.js | 772 ++++++++++++++++++ .../apps/heady_admin_ui/system-map.html | 411 ++++++++++ 4 files changed, 1798 insertions(+) create mode 100644 HeadySystems_v13/apps/heady_admin_ui/css/system-map.css create mode 100644 HeadySystems_v13/apps/heady_admin_ui/js/network-graph.js create mode 100644 HeadySystems_v13/apps/heady_admin_ui/system-map.html diff --git a/HeadySystems_v13/apps/heady_admin_ui/css/system-map.css b/HeadySystems_v13/apps/heady_admin_ui/css/system-map.css new file mode 100644 index 00000000..47f97304 --- /dev/null +++ b/HeadySystems_v13/apps/heady_admin_ui/css/system-map.css @@ -0,0 +1,611 @@ +/* ======================================== + Heady Admin UI - System Map Styles + ======================================== */ + +/* ======================================== + Main Container + ======================================== */ + +.system-map-container { + width: 100%; + height: calc(100vh - 200px); + min-height: 600px; + position: relative; + background: var(--bg-card); + backdrop-filter: blur(20px); + border-radius: var(--radius-xl); + border: 1px solid var(--border-color); + overflow: hidden; + box-shadow: var(--shadow-xl); +} + +/* ======================================== + Canvas + ======================================== */ + +#networkCanvas { + display: block; + width: 100%; + height: 100%; + cursor: grab; + touch-action: none; +} + +#networkCanvas:active { + cursor: grabbing; +} + +/* ======================================== + Control Panel + ======================================== */ + +.control-panel { + position: absolute; + top: 20px; + right: 20px; + background: var(--bg-card); + backdrop-filter: blur(20px); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: var(--spacing-md); + box-shadow: var(--shadow-lg); + z-index: 100; + min-width: 200px; +} + +.control-section { + margin-bottom: var(--spacing-md); + padding-bottom: var(--spacing-md); + border-bottom: 1px solid var(--border-color); +} + +.control-section:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; +} + +.control-section h4 { + font-size: 0.875rem; + color: var(--text-secondary); + margin-bottom: var(--spacing-sm); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +/* Zoom Controls */ +.zoom-controls { + display: flex; + gap: var(--spacing-sm); + align-items: center; +} + +.zoom-btn { + width: 32px; + height: 32px; + background: var(--bg-card-hover); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + color: var(--text-primary); + cursor: pointer; + font-size: 1.125rem; + font-weight: bold; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; +} + +.zoom-btn:hover { + background: var(--color-primary); + border-color: var(--color-primary); + transform: scale(1.1); +} + +.zoom-slider { + flex: 1; + -webkit-appearance: none; + appearance: none; + height: 4px; + background: var(--border-color); + border-radius: var(--radius-full); + outline: none; +} + +.zoom-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 16px; + height: 16px; + background: var(--color-primary); + border-radius: 50%; + cursor: pointer; + transition: all 0.3s ease; +} + +.zoom-slider::-webkit-slider-thumb:hover { + background: var(--color-secondary); + transform: scale(1.2); +} + +.zoom-slider::-moz-range-thumb { + width: 16px; + height: 16px; + background: var(--color-primary); + border-radius: 50%; + cursor: pointer; + border: none; + transition: all 0.3s ease; +} + +.zoom-slider::-moz-range-thumb:hover { + background: var(--color-secondary); + transform: scale(1.2); +} + +/* View Mode Buttons */ +.view-mode-buttons { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); +} + +.view-mode-btn { + width: 100%; + padding: var(--spacing-sm) var(--spacing-md); + background: transparent; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + color: var(--text-primary); + cursor: pointer; + font-size: 0.875rem; + text-align: left; + display: flex; + align-items: center; + gap: var(--spacing-xs); + transition: all 0.3s ease; +} + +.view-mode-btn:hover { + background: var(--bg-card-hover); + border-color: var(--color-primary); +} + +.view-mode-btn.active { + background: var(--gradient-purple); + border-color: transparent; + color: white; +} + +.view-mode-btn .icon { + font-size: 1rem; +} + +/* Filter Controls */ +.filter-controls { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); +} + +.filter-checkbox { + display: flex; + align-items: center; + gap: var(--spacing-sm); + padding: var(--spacing-xs); + cursor: pointer; + border-radius: var(--radius-sm); + transition: background 0.2s ease; +} + +.filter-checkbox:hover { + background: var(--bg-card-hover); +} + +.filter-checkbox input[type="checkbox"] { + width: 18px; + height: 18px; + cursor: pointer; + accent-color: var(--color-primary); +} + +.filter-checkbox label { + flex: 1; + font-size: 0.875rem; + cursor: pointer; +} + +/* Legend */ +.legend { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); +} + +.legend-item { + display: flex; + align-items: center; + gap: var(--spacing-sm); + font-size: 0.875rem; +} + +.legend-color { + width: 12px; + height: 12px; + border-radius: 50%; +} + +.legend-color.healthy { + background: var(--color-success); + box-shadow: 0 0 8px var(--color-success); +} + +.legend-color.warning { + background: var(--color-warning); + box-shadow: 0 0 8px var(--color-warning); +} + +.legend-color.error { + background: var(--color-error); + box-shadow: 0 0 8px var(--color-error); +} + +.legend-color.core { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); +} + +.legend-color.vertical { + background: linear-gradient(135deg, #10b981 0%, #34d399 100%); +} + +.legend-color.infrastructure { + background: linear-gradient(135deg, #f59e0b 0%, #fbbf24 100%); +} + +/* ======================================== + Node Detail Panel + ======================================== */ + +.node-detail-panel { + position: absolute; + top: 20px; + left: 20px; + width: 320px; + max-height: calc(100% - 40px); + background: var(--bg-card); + backdrop-filter: blur(20px); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-xl); + z-index: 100; + overflow: hidden; + transform: translateX(-400px); + transition: transform 0.3s ease; +} + +.node-detail-panel.active { + transform: translateX(0); +} + +.node-detail-header { + padding: var(--spacing-lg); + background: var(--gradient-purple); + color: white; + display: flex; + align-items: center; + justify-content: space-between; +} + +.node-detail-title { + display: flex; + align-items: center; + gap: var(--spacing-sm); + flex: 1; +} + +.node-detail-title .node-icon { + font-size: 2rem; +} + +.node-detail-title h3 { + font-size: 1.25rem; + margin: 0; +} + +.close-panel-btn { + width: 32px; + height: 32px; + background: rgba(255, 255, 255, 0.2); + border: none; + border-radius: var(--radius-md); + color: white; + cursor: pointer; + font-size: 1.25rem; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; +} + +.close-panel-btn:hover { + background: rgba(255, 255, 255, 0.3); + transform: scale(1.1); +} + +.node-detail-content { + padding: var(--spacing-lg); + max-height: calc(100vh - 300px); + overflow-y: auto; +} + +.detail-section { + margin-bottom: var(--spacing-lg); +} + +.detail-section:last-child { + margin-bottom: 0; +} + +.detail-section h4 { + font-size: 0.875rem; + color: var(--text-secondary); + margin-bottom: var(--spacing-sm); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.status-badge { + display: inline-flex; + align-items: center; + gap: var(--spacing-xs); + padding: var(--spacing-xs) var(--spacing-sm); + border-radius: var(--radius-full); + font-size: 0.75rem; + font-weight: 600; +} + +.status-badge.operational { + background: rgba(16, 185, 129, 0.2); + color: var(--color-success); +} + +.status-badge.degraded { + background: rgba(245, 158, 11, 0.2); + color: var(--color-warning); +} + +.status-badge.offline { + background: rgba(239, 68, 68, 0.2); + color: var(--color-error); +} + +.uptime-display { + font-size: 1.5rem; + font-weight: 700; + color: var(--color-success); + margin-top: var(--spacing-xs); +} + +.connected-nodes-list { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); +} + +.connected-node-item { + display: flex; + align-items: center; + gap: var(--spacing-sm); + padding: var(--spacing-sm); + background: rgba(255, 255, 255, 0.05); + border-radius: var(--radius-md); + font-size: 0.875rem; + cursor: pointer; + transition: all 0.3s ease; +} + +.connected-node-item:hover { + background: rgba(255, 255, 255, 0.1); + transform: translateX(5px); +} + +.connected-node-item .icon { + font-size: 1.25rem; +} + +.activity-timeline { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); +} + +.activity-item { + display: flex; + gap: var(--spacing-sm); + font-size: 0.875rem; +} + +.activity-time { + color: var(--text-secondary); + font-size: 0.75rem; + white-space: nowrap; +} + +.activity-text { + flex: 1; +} + +.quick-actions { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); +} + +.action-btn { + width: 100%; + padding: var(--spacing-sm) var(--spacing-md); + background: var(--bg-card-hover); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + color: var(--text-primary); + cursor: pointer; + font-size: 0.875rem; + text-align: left; + display: flex; + align-items: center; + gap: var(--spacing-sm); + transition: all 0.3s ease; +} + +.action-btn:hover { + background: var(--gradient-purple); + border-color: transparent; + color: white; + transform: translateX(5px); +} + +.action-btn .icon { + font-size: 1rem; +} + +/* ======================================== + Tooltip + ======================================== */ + +.network-tooltip { + position: absolute; + background: rgba(0, 0, 0, 0.9); + backdrop-filter: blur(10px); + color: white; + padding: var(--spacing-sm) var(--spacing-md); + border-radius: var(--radius-md); + font-size: 0.875rem; + pointer-events: none; + z-index: 1000; + opacity: 0; + transform: translate(-50%, -100%) translateY(-10px); + transition: opacity 0.2s ease; + white-space: nowrap; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + +.network-tooltip.active { + opacity: 1; +} + +.tooltip-title { + font-weight: 600; + margin-bottom: 2px; +} + +.tooltip-stats { + display: flex; + gap: var(--spacing-md); + font-size: 0.75rem; + color: rgba(255, 255, 255, 0.8); +} + +/* ======================================== + Loading State + ======================================== */ + +.loading-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--bg-card); + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + gap: var(--spacing-md); + z-index: 200; +} + +.loading-spinner { + width: 48px; + height: 48px; + border: 4px solid var(--border-color); + border-top-color: var(--color-primary); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +.loading-text { + color: var(--text-secondary); + font-size: 0.875rem; +} + +/* ======================================== + Responsive Design + ======================================== */ + +@media (max-width: 768px) { + .system-map-container { + height: calc(100vh - 150px); + min-height: 400px; + } + + .control-panel { + top: 10px; + right: 10px; + min-width: 160px; + padding: var(--spacing-sm); + } + + .node-detail-panel { + width: calc(100% - 20px); + left: 10px; + top: 10px; + } + + .node-detail-panel.active { + transform: translateY(0); + } + + .node-detail-panel:not(.active) { + transform: translateY(-600px); + } +} + +@media (max-width: 480px) { + .control-panel { + position: fixed; + bottom: 10px; + top: auto; + right: 10px; + left: 10px; + max-width: calc(100% - 20px); + } + + .view-mode-buttons { + flex-direction: row; + flex-wrap: wrap; + } + + .view-mode-btn { + flex: 1; + min-width: 120px; + } +} + +/* ======================================== + Accessibility + ======================================== */ + +@media (prefers-reduced-motion: reduce) { + .node-detail-panel, + .network-tooltip { + transition: none; + } +} + +/* High contrast mode support */ +@media (prefers-contrast: high) { + .control-panel, + .node-detail-panel { + border: 2px solid var(--text-primary); + } +} diff --git a/HeadySystems_v13/apps/heady_admin_ui/index.html b/HeadySystems_v13/apps/heady_admin_ui/index.html index 0087274d..4c8b6ca7 100644 --- a/HeadySystems_v13/apps/heady_admin_ui/index.html +++ b/HeadySystems_v13/apps/heady_admin_ui/index.html @@ -28,6 +28,10 @@

πŸ“Š Dashboard + + πŸ—ΊοΈ + System Map + + + 🎯 + Verticals + + +
+ +
+ + + + +
+ + +
+

+ πŸ—ΊοΈ + Interactive System Topology +

+ + +
+ +
+
+
Initializing network topology...
+
+ + + + + +
+
+
+
+ + +
+
+
+ ⚑ +

Node Details

+
+ +
+
+ +
+

Status & Health

+
Operational
+
99.98%
+

Uptime

+
+ + +
+

Connected Nodes

+
+ +
+
+ + +
+

Recent Activity

+
+
+ 2 min ago + Health check passed +
+
+ 8 min ago + Data sync completed +
+
+ 15 min ago + Configuration updated +
+
+
+ + +
+

Quick Actions

+
+ + + +
+
+
+
+ + +
+ +
+

Zoom

+
+ + + +
+
+ + +
+

Layout

+
+ + + +
+
+ + +
+

Filters

+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+

Legend

+
+
+
+ Healthy +
+
+
+ Warning +
+
+
+ Error +
+
+
+
+ Core +
+
+
+ Vertical +
+
+
+ Infrastructure +
+
+
+
+
+ + +
+

+ πŸ’‘ + How to Use +

+
+
+ πŸ–±οΈ Drag Nodes: +

+ Click and drag nodes to reposition them +

+
+
+ πŸ‘† Click for Details: +

+ Single-click a node to view detailed information +

+
+
+ πŸ–±οΈ Double-Click: +

+ Double-click to navigate to the vertical's dashboard +

+
+
+ πŸ” Zoom & Pan: +

+ Use mouse wheel to zoom, drag canvas to pan +

+
+
+ ⌨️ Keyboard: +

+ Use arrow keys to move selected node, Esc to close +

+
+
+ πŸ“± Touch Support: +

+ Pinch to zoom, drag to pan on mobile devices +

+
+
+
+
+ +
+ + + + + + + + + + +