@@ -256,6 +256,11 @@ const NetworkMonitor = () => {
256256 // AVG latency stuff
257257 const [ deviceStats , setDeviceStats ] = useState ( { } ) ;
258258
259+ // Node editing stuff
260+ const [ editingDevice , setEditingDevice ] = useState ( null ) ;
261+ const [ editingBox , setEditingBox ] = useState ( null ) ;
262+ const [ editForm , setEditForm ] = useState ( { name : '' , ip : '' , type : '' , color : '' } ) ;
263+
259264 const devicesRef = React . useRef ( devices ) ;
260265
261266 // Load configuration on mount
@@ -568,6 +573,53 @@ const NetworkMonitor = () => {
568573 }
569574 } ;
570575
576+ const startEditDevice = ( device ) => {
577+ setEditingDevice ( device . id ) ;
578+ setEditForm ( {
579+ name : device . name ,
580+ ip : device . ip ,
581+ type : device . type
582+ } ) ;
583+ } ;
584+
585+ const saveDeviceEdit = ( ) => {
586+ if ( editForm . name && editForm . ip ) {
587+ setDevices ( prev => prev . map ( d =>
588+ d . id === editingDevice
589+ ? { ...d , name : editForm . name , ip : editForm . ip , type : editForm . type }
590+ : d
591+ ) ) ;
592+ setEditingDevice ( null ) ;
593+ setEditForm ( { name : '' , ip : '' , type : '' , color : '' } ) ;
594+ }
595+ } ;
596+
597+ const cancelEdit = ( ) => {
598+ setEditingDevice ( null ) ;
599+ setEditingBox ( null ) ;
600+ setEditForm ( { name : '' , ip : '' , type : '' , color : '' } ) ;
601+ } ;
602+
603+ const startEditBox = ( box ) => {
604+ setEditingBox ( box . id ) ;
605+ setEditForm ( {
606+ name : box . name ,
607+ color : box . color
608+ } ) ;
609+ } ;
610+
611+ const saveBoxEdit = ( ) => {
612+ if ( editForm . name ) {
613+ setBoxes ( prev => prev . map ( b =>
614+ b . id === editingBox
615+ ? { ...b , name : editForm . name , color : editForm . color }
616+ : b
617+ ) ) ;
618+ setEditingBox ( null ) ;
619+ setEditForm ( { name : '' , ip : '' , type : '' , color : '' } ) ;
620+ }
621+ } ;
622+
571623 const addDevice = ( ) => {
572624 if ( newDevice . name && newDevice . ip ) {
573625 setDevices ( prev => [ ...prev , {
@@ -817,6 +869,109 @@ showAddBox && React.createElement(
817869 } , 'Cancel' )
818870 )
819871 ) ,
872+ ( editingDevice || editingBox ) && React . createElement (
873+ 'div' ,
874+ {
875+ className : 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50' ,
876+ onClick : cancelEdit
877+ } ,
878+ React . createElement (
879+ 'div' ,
880+ {
881+ className : 'bg-gray-800 rounded-lg p-6 border border-gray-700 min-w-96' ,
882+ onClick : ( e ) => e . stopPropagation ( )
883+ } ,
884+ React . createElement ( 'h2' , { className : 'text-xl font-bold text-white mb-4' } ,
885+ editingDevice ? 'Edit Device' : 'Edit Box'
886+ ) ,
887+ React . createElement (
888+ 'div' ,
889+ { className : 'space-y-4' } ,
890+ React . createElement (
891+ 'div' ,
892+ { } ,
893+ React . createElement ( 'label' , { className : 'text-gray-400 text-sm block mb-1' } ,
894+ editingDevice ? 'Device Name' : 'Box Name'
895+ ) ,
896+ React . createElement ( 'input' , {
897+ type : 'text' ,
898+ value : editForm . name ,
899+ onChange : ( e ) => setEditForm ( { ...editForm , name : e . target . value } ) ,
900+ className : 'w-full px-3 py-2 bg-gray-700 text-white rounded border border-gray-600 focus:outline-none focus:border-blue-500'
901+ } )
902+ ) ,
903+ editingDevice && React . createElement (
904+ 'div' ,
905+ { } ,
906+ React . createElement ( 'label' , { className : 'text-gray-400 text-sm block mb-1' } , 'IP Address' ) ,
907+ React . createElement ( 'input' , {
908+ type : 'text' ,
909+ value : editForm . ip ,
910+ onChange : ( e ) => setEditForm ( { ...editForm , ip : e . target . value } ) ,
911+ className : 'w-full px-3 py-2 bg-gray-700 text-white rounded border border-gray-600 focus:outline-none focus:border-blue-500'
912+ } )
913+ ) ,
914+ editingDevice && React . createElement (
915+ 'div' ,
916+ { } ,
917+ React . createElement ( 'label' , { className : 'text-gray-400 text-sm block mb-1' } , 'Type' ) ,
918+ React . createElement (
919+ 'select' ,
920+ {
921+ value : editForm . type ,
922+ onChange : ( e ) => setEditForm ( { ...editForm , type : e . target . value } ) ,
923+ className : 'w-full px-3 py-2 bg-gray-700 text-white rounded border border-gray-600 focus:outline-none focus:border-blue-500'
924+ } ,
925+ React . createElement ( 'option' , { value : 'router' } , 'Router' ) ,
926+ React . createElement ( 'option' , { value : 'server' } , 'Server' ) ,
927+ React . createElement ( 'option' , { value : 'wifi' } , 'WiFi AP' ) ,
928+ React . createElement ( 'option' , { value : 'storage' } , 'Storage' ) ,
929+ React . createElement ( 'option' , { value : 'monitor' } , 'End-User Device' ) ,
930+ React . createElement ( 'option' , { value : 'switch' } , 'Switch' )
931+ )
932+ ) ,
933+ editingBox && React . createElement (
934+ 'div' ,
935+ { } ,
936+ React . createElement ( 'label' , { className : 'text-gray-400 text-sm block mb-1' } , 'Color' ) ,
937+ React . createElement (
938+ 'select' ,
939+ {
940+ value : editForm . color ,
941+ onChange : ( e ) => setEditForm ( { ...editForm , color : e . target . value } ) ,
942+ className : 'w-full px-3 py-2 bg-gray-700 text-white rounded border border-gray-600 focus:outline-none focus:border-blue-500'
943+ } ,
944+ React . createElement ( 'option' , { value : 'blue' } , 'Blue' ) ,
945+ React . createElement ( 'option' , { value : 'green' } , 'Green' ) ,
946+ React . createElement ( 'option' , { value : 'purple' } , 'Purple' ) ,
947+ React . createElement ( 'option' , { value : 'red' } , 'Red' ) ,
948+ React . createElement ( 'option' , { value : 'yellow' } , 'Yellow' ) ,
949+ React . createElement ( 'option' , { value : 'orange' } , 'Orange' )
950+ )
951+ ) ,
952+ React . createElement (
953+ 'div' ,
954+ { className : 'flex gap-2 mt-6' } ,
955+ React . createElement (
956+ 'button' ,
957+ {
958+ onClick : editingDevice ? saveDeviceEdit : saveBoxEdit ,
959+ className : 'flex-1 bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded'
960+ } ,
961+ 'Save'
962+ ) ,
963+ React . createElement (
964+ 'button' ,
965+ {
966+ onClick : cancelEdit ,
967+ className : 'flex-1 bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded'
968+ } ,
969+ 'Cancel'
970+ )
971+ )
972+ )
973+ )
974+ ) ,
820975 React . createElement (
821976 'div' ,
822977 {
@@ -970,57 +1125,83 @@ showAddBox && React.createElement(
9701125 'div' ,
9711126 {
9721127 key : box . id ,
973- className : ` absolute border-2 ${ boxColors [ box . color ] } bg-transparent rounded-lg group` ,
1128+ className : ' absolute rounded-lg group' ,
9741129 style : {
9751130 left : `${ box . x } px` ,
9761131 top : `${ box . y } px` ,
9771132 width : `${ box . width } px` ,
9781133 height : `${ box . height } px` ,
9791134 zIndex : 2 ,
9801135 pointerEvents : 'none' // fix because i couldn't hover the connection lines while they were behind a box
981- } ,
982- onMouseDown : ( e ) => { //yah i broke dragging the box with the connection line fix.. smh
983- const rect = e . currentTarget . getBoundingClientRect ( ) ;
984- const borderWidth = 2 ;
985- const clickX = e . clientX - rect . left ;
986- const clickY = e . clientY - rect . top ;
987- const onBorder = clickX < borderWidth || clickX > rect . width - borderWidth ||
988- clickY < borderWidth || clickY > rect . height - borderWidth ;
989-
990- if ( onBorder ) {
991- handleBoxMouseDown ( e , box )
992- }
993- }
1136+ }
9941137 } ,
9951138 React . createElement ( 'div' , {
1139+ className : `absolute top-0 left-0 right-0 border-t-2 ${ boxColors [ box . color ] } ` ,
9961140 style : {
997- position : 'absolute' ,
998- top : '2px' ,
999- left : '2px' ,
1000- right : '2px' ,
1001- bottom : '2px' ,
1002- pointerEvents : 'none'
1003- }
1141+ height : '8px' ,
1142+ pointerEvents : 'none' ,
1143+ cursor : 'move'
1144+ } ,
1145+ onMouseDown : ( e ) => handleBoxMouseDown ( e , box )
10041146 } ) ,
1147+ React . createElement ( 'div' , {
1148+ className : `absolute bottom-0 left-0 right-0 border-b-2 ${ boxColors [ box . color ] } ` ,
1149+ style : {
1150+ height : '8px' ,
1151+ pointerEvents : 'auto' ,
1152+ cursor : 'move'
1153+ } ,
1154+ onMouseDown : ( e ) => handleBoxMouseDown ( e , box )
1155+ } ) ,
1156+ React . createElement ( 'div' , {
1157+ className : `absolute top-0 bottom-0 left-0 border-l-2 ${ boxColors [ box . color ] } ` ,
1158+ style : {
1159+ width : '8px' ,
1160+ pointerEvents : 'auto' ,
1161+ cursor : 'move'
1162+ } ,
1163+ onMouseDown : ( e ) => handleBoxMouseDown ( e , box )
1164+ } ) ,
1165+ React . createElement ( 'div' , {
1166+ className : `absolute top-0 bottom-0 right-0 border-r-2 ${ boxColors [ box . color ] } ` ,
1167+ style : {
1168+ width : '8px' ,
1169+ pointerEvents : 'auto' ,
1170+ cursor : 'move'
1171+ } ,
1172+ onMouseDown : ( e ) => handleBoxMouseDown ( e , box )
1173+ } ) ,
1174+ React . createElement ( 'div' , {
1175+ className : `absolute inset-0 border-2 ${ boxColors [ box . color ] } rounded-lg` ,
1176+ style : { pointerEvents : 'none' }
1177+ } ) ,
10051178 React . createElement (
10061179 'div' ,
10071180 {
1008- className : 'absolute -top-6 left-0 bg-gray-800 px-2 py-1 rounded text-white text-sm font-semibold' } ,
1181+ className : 'absolute -top-6 left-0 bg-gray-800 px-2 py-1 rounded text-white text-sm font-semibold cursor-pointer hover:bg-gray-700' ,
1182+ style : { pointerEvents : 'auto' } ,
1183+ onClick : ( e ) => {
1184+ e . stopPropagation ( ) ;
1185+ startEditBox ( box ) ;
1186+ }
1187+ } ,
10091188 box . name
10101189 ) ,
10111190 React . createElement (
10121191 'button' ,
10131192 {
10141193 onClick : ( ) => removeBox ( box . id ) ,
10151194 className : 'absolute -top-2 -right-2 bg-red-600 hover:bg-red-700 rounded-full p-1 opacity-0 group-hover:opacity-100 transition-opacity z-10' ,
1016- onMouseDown : ( e ) => e . stopPropagation ( )
1195+ onMouseDown : ( e ) => e . stopPropagation ( ) ,
1196+ style : { pointerEvents : 'auto' }
10171197 } ,
10181198 React . createElement ( XIcon , { size : 12 } )
10191199 ) ,
10201200 React . createElement (
10211201 'div' ,
10221202 {
10231203 className : 'absolute bottom-0 right-0 w-4 h-4 cursor-nwse-resize' ,
1204+ style : { pointerEvents : 'auto' } ,
10241205 onMouseDown : ( e ) => {
10251206 e . stopPropagation ( ) ;
10261207 setResizingBox ( box . id ) ;
@@ -1065,6 +1246,32 @@ showAddBox && React.createElement(
10651246 } ,
10661247 React . createElement ( XIcon , { size : 12 } )
10671248 ) ,
1249+ React . createElement (
1250+ 'button' ,
1251+ {
1252+ onClick : ( e ) => {
1253+ e . stopPropagation ( ) ;
1254+ startEditDevice ( device ) ;
1255+ } ,
1256+ className : 'absolute -top-2 -right-12 bg-blue-600 hover:bg-blue-700 rounded-full p-1 opacity-0 group-hover:opacity-100 transition-opacity z-10' ,
1257+ onMouseDown : ( e ) => e . stopPropagation ( )
1258+ } ,
1259+ React . createElement ( 'svg' , {
1260+ xmlns : 'http://www.w3.org/2000/svg' ,
1261+ fill : 'none' ,
1262+ viewBox : '0 0 24 24' ,
1263+ strokeWidth : 2 ,
1264+ stroke : 'currentColor' ,
1265+ width : 12 ,
1266+ height : 12
1267+ } ,
1268+ React . createElement ( 'path' , {
1269+ strokeLinecap : 'round' ,
1270+ strokeLinejoin : 'round' ,
1271+ d : 'M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10'
1272+ } )
1273+ )
1274+ ) ,
10681275 React . createElement (
10691276 'div' ,
10701277 { className : 'flex flex-col items-center' } ,
0 commit comments