From c80e6d3474d974e440e1f6eecd8461c89d4e93c0 Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Mon, 14 Jul 2025 20:42:12 +1000 Subject: [PATCH] css hover box #724 --- front/css/app.css | 6 ++- front/css/system-dark-patch.css | 4 ++ front/js/settings_utils.js | 3 ++ front/js/ui_components.js | 90 ++++++++++++++++++++++++++++++++- front/network.php | 11 +++- 5 files changed, 110 insertions(+), 4 deletions(-) diff --git a/front/css/app.css b/front/css/app.css index ca29c37f..14625ac0 100755 --- a/front/css/app.css +++ b/front/css/app.css @@ -1716,6 +1716,10 @@ input[readonly] { width: auto; } +#hover-box +{ + background-color: #ffffff;; +} #networkTree .netCollapse { @@ -1726,7 +1730,7 @@ input[readonly] { #networkTree .highlightedNode { /* border: solid; */ - border-color:cyan; + border-color:#3c8dbc; } #networkTree .netStatus-Off-line i, #networkTree .netStatus-Off-line svg diff --git a/front/css/system-dark-patch.css b/front/css/system-dark-patch.css index b98d29be..3468637b 100755 --- a/front/css/system-dark-patch.css +++ b/front/css/system-dark-patch.css @@ -758,6 +758,10 @@ color: #bec5cb; } + #hover-box + { + background-color: #353c42 !important; + } } diff --git a/front/js/settings_utils.js b/front/js/settings_utils.js index 353878a1..ec1caae4 100755 --- a/front/js/settings_utils.js +++ b/front/js/settings_utils.js @@ -689,6 +689,9 @@ function reverseTransformers(val, transformers) { mac = val // value is mac val = `${getDevDataByMac(mac, "devName")}` break; + case "deviceRelType": + val = val; // nothing to do + break; default: console.warn(`Unknown transformer: ${transformer}`); } diff --git a/front/js/ui_components.js b/front/js/ui_components.js index 757544eb..417da88b 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -809,11 +809,99 @@ function initSelect2() { } } +// ------------------------------------------ +// Display device info on hover (attach only once) +function initHoverNodeInfo() { + if ($('#hover-box').length === 0) { + $('
').appendTo('body').hide().css({ + position: 'absolute', + zIndex: 9999, + border: '1px solid #ccc', + borderRadius: '8px', + padding: '10px', + boxShadow: '0 4px 12px rgba(0,0,0,0.15)', + minWidth: '200px', + maxWidth: '300px', + fontSize: '14px', + pointerEvents: 'none', + backgroundColor: '#fff' + }); + } + + if (initHoverNodeInfo._handlersAttached) return; + initHoverNodeInfo._handlersAttached = true; + + let hoverTimeout = null; + let lastTarget = null; + + $(document).on('mouseenter', '.hover-node-info', function (e) { + const $el = $(this); + lastTarget = this; + + clearTimeout(hoverTimeout); + + hoverTimeout = setTimeout(() => { + if (lastTarget !== this) return; + + const name = $el.data('name') || 'Unknown'; + const ip = $el.data('ip') || 'N/A'; + const mac = $el.data('mac') || 'N/A'; + const vendor = $el.data('vendor') || 'Unknown'; + const relationship = $el.data('relationship') || 'Unknown'; + + const html = ` + ${name}
+ IP: ${ip}
+ MAC: ${mac}
+ Vendor: ${vendor}
+ Relationship: ${relationship} + `; + + $('#hover-box').html(html).fadeIn(150); + }, 300); + }); + + $(document).on('mousemove', '.hover-node-info', function (e) { + const hoverBox = $('#hover-box'); + const boxWidth = hoverBox.outerWidth(); + const boxHeight = hoverBox.outerHeight(); + const padding = 15; + + const winWidth = $(window).width(); + const winHeight = $(window).height(); + + let left = e.pageX + padding; + let top = e.pageY + padding; + + // Position leftward if close to right edge + if (e.pageX + boxWidth + padding > winWidth) { + left = e.pageX - boxWidth - padding; + } + + // Position upward if close to bottom edge + if (e.pageY + boxHeight + padding > winHeight) { + top = e.pageY - boxHeight - padding; + } + + hoverBox.css({ top: top + 'px', left: left + 'px' }); + }); + + $(document).on('mouseleave', '.hover-node-info', function () { + clearTimeout(hoverTimeout); + lastTarget = null; + $('#hover-box').fadeOut(100); + }); +} + + + + // init functions after dom loaded window.addEventListener("load", function() { // try to initialize setTimeout(() => { - initSelect2() + initSelect2(); + initHoverNodeInfo(); // initializeiCheck(); }, 500); }); diff --git a/front/network.php b/front/network.php index ae5d5301..9260f6cd 100755 --- a/front/network.php +++ b/front/network.php @@ -582,6 +582,8 @@ function getChildren(node, list, path, visited = []) parentMac: node.devParentMAC, icon: node.devIcon, type: node.devType, + vendor: node.devVendor, + ip: node.devLastIP, status: node.devStatus, hasChildren: children.length > 0 || hiddenMacs.includes(node.devMac), relType: node.devParentRelType, @@ -749,10 +751,15 @@ function initTree(myHierarchy) statusCss = ` netStatus-${nodeData.data.status}`; return result = `
${devicePort} ${deviceIcon} @@ -776,7 +783,7 @@ function initTree(myHierarchy) relationnalField: "children", linkWidth: (nodeData) => 3, linkColor: (nodeData) => { - + relConf = getRelationshipConf(nodeData.data.relType) return relConf.color;