@@ -2,167 +2,128 @@ import React from "react";
22import { useGridStackContext } from "./lib/grid-stack-context" ;
33import { Dropdown , DropdownItem } from "flowbite-react" ;
44import { MdSpeed } from 'react-icons/md' ;
5- import { FaBatteryHalf , FaBolt , FaCog , FaEye , FaGlobe , FaPlus } from 'react-icons/fa' ;
5+ import { FaBatteryHalf , FaBolt , FaCog , FaEye , FaGlobe , FaPlug , FaPlus , FaSlidersH } from 'react-icons/fa' ;
66import { BsRulers } from 'react-icons/bs' ;
77import { FlowBiteConstants } from "@/utils/constants" ;
88import { useTranslation } from "react-i18next" ;
9+ import { getCustomSensors } from "./sensors/customRegistry" ;
910
10- type ActionType = 'accelerometer' | 'current' | 'encoder' | 'gyroscope' | 'rangefinder' | 'reflectance' | 'voltage' ;
11+
12+ interface BuiltinSensorDef {
13+ action : string ;
14+ icon : React . ComponentType < { size ?: number } > ;
15+ titleKey : string ;
16+ gridH : number ;
17+ gridW : number ;
18+ minW : number ;
19+ minH : number ;
20+ componentName : string ;
21+ }
22+
23+ const BUILTIN_SENSORS : BuiltinSensorDef [ ] = [
24+ { action : 'accelerometer' , icon : MdSpeed , titleKey : 'accelerometer' , gridH : 5 , gridW : 4 , minW : 2 , minH : 5 , componentName : 'Accelerometer' } ,
25+ { action : 'current' , icon : FaBolt , titleKey : 'current' , gridH : 4 , gridW : 4 , minW : 1 , minH : 5 , componentName : 'Current' } ,
26+ { action : 'gyroscope' , icon : FaGlobe , titleKey : 'gyroscope' , gridH : 4 , gridW : 4 , minW : 2 , minH : 5 , componentName : 'Gyroscope' } ,
27+ { action : 'encoder' , icon : FaCog , titleKey : 'encoders' , gridH : 5 , gridW : 4 , minW : 1 , minH : 4 , componentName : 'Encoder' } ,
28+ { action : 'reflectance' , icon : FaEye , titleKey : 'reflectance' , gridH : 5 , gridW : 4 , minW : 2 , minH : 5 , componentName : 'Reflectance' } ,
29+ { action : 'rangefinder' , icon : BsRulers , titleKey : 'rangefinder' , gridH : 8 , gridW : 4 , minW : 2 , minH : 8 , componentName : 'Rangefinder' } ,
30+ { action : 'voltage' , icon : FaBatteryHalf , titleKey : 'voltage' , gridH : 6 , gridW : 4 , minW : 2 , minH : 6 , componentName : 'Voltage' } ,
31+ ] ;
1132
1233const AddWidgets : React . FC = ( ) => {
1334 const { t } = useTranslation ( ) ;
1435 const { addWidget } = useGridStackContext ( ) ;
1536
16- const handleAction = ( action : ActionType ) => {
17- switch ( action ) {
18- case 'accelerometer' : {
19- const node = ( ) => ( {
20- // Remove custom id - let GridStack auto-generate
21- h : 5 ,
22- w : 4 ,
23- x : 0 ,
24- y : 2 ,
25- minW : 2 ,
26- minH : 5 ,
27- content : JSON . stringify ( {
28- name : 'Accelerometer' ,
29- props : {
30- isActive : true
31- // Remove widgetId - we'll get it from GridStack
32- } ,
33- } ) ,
34- } ) ;
35- addWidget ( node ) ;
36- console . log ( 'Accelerometer action triggered' ) ;
37- break ;
38- }
39- case 'current' : {
40- const node = ( ) => ( {
41- h : 4 ,
42- w : 4 ,
43- x : 0 ,
44- y : 2 ,
45- minW : 1 ,
46- minH : 5 ,
47- content : JSON . stringify ( {
48- name : 'Current' ,
49- props : {
50- isActive : true
51- } ,
52- } ) ,
53- } ) ;
54- addWidget ( node ) ;
55- console . log ( 'Current sensor action triggered' ) ;
56- break ;
57- }
58- case 'gyroscope' : {
59- const node = ( ) => ( {
60- h : 4 ,
61- w : 4 ,
62- x : 0 ,
63- y : 2 ,
64- minW : 2 ,
65- minH : 5 ,
66- content : JSON . stringify ( {
67- name : 'Gyroscope' ,
68- props : {
69- isActive : true
70- } ,
71- } ) ,
72- } ) ;
73- addWidget ( node ) ;
74- console . log ( 'Gyroscope action triggered' ) ;
75- break ;
76- }
77- case 'encoder' : {
78- const node = ( ) => ( {
79- h : 5 ,
80- w : 4 ,
81- x : 0 ,
82- y : 2 ,
83- minW : 1 ,
84- minH : 4 ,
85- content : JSON . stringify ( {
86- name : 'Encoder' ,
87- props : {
88- isActive : true
89- } ,
90- } ) ,
91- } ) ;
92- addWidget ( node ) ;
93- console . log ( 'Encoder action triggered' ) ;
94- break ;
95- }
96- case 'reflectance' : {
97- const node = ( ) => ( {
98- h : 5 ,
99- w : 4 ,
100- x : 0 ,
101- y : 2 ,
102- minW : 2 ,
103- minH : 5 ,
104- content : JSON . stringify ( {
105- name : 'Reflectance' ,
106- props : {
107- isActive : true
108- } ,
109- } ) ,
110- } ) ;
111- addWidget ( node ) ;
112- console . log ( 'Reflectance action triggered' ) ;
113- break ;
114- }
115- case 'voltage' : {
116- const node = ( ) => ( {
117- h : 6 ,
118- w : 4 ,
119- x : 0 ,
120- y : 2 ,
121- minW : 2 ,
122- minH : 6 ,
123- content : JSON . stringify ( {
124- name : 'Voltage' ,
125- props : {
126- isActive : true
127- } ,
128- } ) ,
129- } ) ;
130- addWidget ( node ) ;
131- console . log ( 'Voltage action triggered' ) ;
132- break ;
133- }
134- case 'rangefinder' : {
135- const node = ( ) => ( {
136- h : 8 ,
137- w : 4 ,
138- x : 0 ,
139- y : 2 ,
140- minW : 2 ,
141- minH : 8 ,
142- content : JSON . stringify ( {
143- name : 'Rangefinder' ,
144- props : {
145- isActive : true
146- } ,
147- } ) ,
148- } ) ;
149- addWidget ( node ) ;
150- console . log ( 'Rangefinder action triggered' ) ;
151- break ;
152- }
153- }
37+ const customSensors = getCustomSensors ( ) ;
38+
39+ const handleAddBuiltin = ( def : BuiltinSensorDef ) => {
40+ addWidget ( ( ) => ( {
41+ h : def . gridH ,
42+ w : def . gridW ,
43+ x : 0 ,
44+ y : 2 ,
45+ minW : def . minW ,
46+ minH : def . minH ,
47+ content : JSON . stringify ( {
48+ name : def . componentName ,
49+ props : { isActive : true } ,
50+ } ) ,
51+ } ) ) ;
52+ } ;
53+
54+ const handleAddCustom = ( sensorName : string ) => {
55+ const def = customSensors . find ( s => s . sensorName === sensorName ) ;
56+ if ( ! def ) return ;
57+
58+ const grid = def . gridDefaults ?? { } ;
59+ addWidget ( ( ) => ( {
60+ h : grid . h ?? 5 ,
61+ w : grid . w ?? 4 ,
62+ x : 0 ,
63+ y : 2 ,
64+ minW : grid . minW ?? 2 ,
65+ minH : grid . minH ?? 5 ,
66+ content : JSON . stringify ( {
67+ name : 'CustomSensor' ,
68+ props : { sensorName : def . sensorName } ,
69+ } ) ,
70+ } ) ) ;
15471 } ;
15572
15673 return (
15774 < div className = "flex items-center mt-4 sm:mt-0" >
158- < Dropdown label = { < FaPlus size = { 20 } /> } inline = { true } theme = { FlowBiteConstants . DropdownTheme } className = "flex items-center mt-4 sm:mt-0 " >
159- < DropdownItem icon = { MdSpeed } onClick = { ( ) => handleAction ( 'accelerometer' ) } > { t ( 'accelerometer' ) } </ DropdownItem >
160- < DropdownItem icon = { FaBolt } onClick = { ( ) => handleAction ( 'current' ) } > { t ( 'current' ) } </ DropdownItem >
161- < DropdownItem icon = { FaGlobe } onClick = { ( ) => handleAction ( 'gyroscope' ) } > { t ( 'gyroscope' ) } </ DropdownItem >
162- < DropdownItem icon = { FaCog } onClick = { ( ) => handleAction ( 'encoder' ) } > { t ( 'encoders' ) } </ DropdownItem >
163- < DropdownItem icon = { FaEye } onClick = { ( ) => handleAction ( 'reflectance' ) } > { t ( 'reflectance' ) } </ DropdownItem >
164- < DropdownItem icon = { BsRulers } onClick = { ( ) => handleAction ( 'rangefinder' ) } > { t ( 'rangefinder' ) } </ DropdownItem >
165- < DropdownItem icon = { FaBatteryHalf } onClick = { ( ) => handleAction ( 'voltage' ) } > { t ( 'voltage' ) } </ DropdownItem >
75+ < Dropdown
76+ label = { < FaPlus size = { 20 } /> }
77+ inline = { true }
78+ theme = { FlowBiteConstants . DropdownTheme }
79+ className = "flex items-center mt-4 sm:mt-0"
80+ >
81+ { /* Built-in sensors */ }
82+ { BUILTIN_SENSORS . map ( ( def ) => (
83+ < DropdownItem
84+ key = { def . action }
85+ icon = { def . icon as any }
86+ onClick = { ( ) => handleAddBuiltin ( def ) }
87+ >
88+ { t ( def . titleKey ) }
89+ </ DropdownItem >
90+ ) ) }
91+
92+ { /* Custom Variable (bidirectional XPP variable inspector/editor) */ }
93+ < hr className = "my-1 border-gray-200" />
94+ < DropdownItem
95+ icon = { FaSlidersH }
96+ onClick = { ( ) => {
97+ addWidget ( ( ) => ( {
98+ h : 5 ,
99+ w : 4 ,
100+ x : 0 ,
101+ y : 2 ,
102+ minW : 2 ,
103+ minH : 4 ,
104+ content : JSON . stringify ( {
105+ name : 'CustomVariable' ,
106+ props : { } ,
107+ } ) ,
108+ } ) ) ;
109+ } }
110+ >
111+ { 'Custom Variable' }
112+ </ DropdownItem >
113+ { customSensors . length > 0 && (
114+ < >
115+ < hr className = "my-1 border-gray-200" />
116+ { customSensors . map ( ( def ) => (
117+ < DropdownItem
118+ key = { def . sensorName }
119+ icon = { FaPlug }
120+ onClick = { ( ) => handleAddCustom ( def . sensorName ) }
121+ >
122+ { def . title }
123+ </ DropdownItem >
124+ ) ) }
125+ </ >
126+ ) }
166127 </ Dropdown >
167128 </ div >
168129 ) ;
0 commit comments