1+ import { useState } from "react" ;
2+ import { Button , Form , Modal } from "react-bootstrap" ;
13import {
24 DeviceFeedbacks ,
35 DeviceMethods ,
68 useGetDeviceFeedbacksQuery ,
79 useGetDeviceMethodsQuery ,
810 useGetDevicePropertiesQuery ,
11+ useSetDeviceJsonCommandMutation ,
912} from "../store/apiSlice" ;
1013
1114const DeviceDetail = ( { item } : DeviceDetailProps ) => {
@@ -30,6 +33,7 @@ const DeviceDetail = ({ item }: DeviceDetailProps) => {
3033 properties = { properties }
3134 methods = { methods }
3235 feedbacks = { feedbacks }
36+ deviceKey = { item . Key }
3337 />
3438 ) ;
3539} ;
@@ -44,80 +48,183 @@ const DeviceDetailRender = ({
4448 properties,
4549 methods,
4650 feedbacks,
51+ deviceKey,
4752} : DeviceDetailRenderProps ) => {
53+ const [ selectedMethod , setSelectedMethod ] = useState < DeviceMethods | null > ( null ) ;
54+ const [ paramValues , setParamValues ] = useState < Record < string , string > > ( { } ) ;
55+ const [ executeMethod , { isLoading : isExecuting } ] = useSetDeviceJsonCommandMutation ( ) ;
56+
57+ const handleOpen = ( method : DeviceMethods ) => {
58+ setSelectedMethod ( method ) ;
59+ setParamValues ( Object . fromEntries ( method . Params . map ( ( p ) => [ p . Name , "" ] ) ) ) ;
60+ } ;
61+
62+ const handleClose = ( ) => {
63+ setSelectedMethod ( null ) ;
64+ setParamValues ( { } ) ;
65+ } ;
66+
67+ const handleExecute = async ( ) => {
68+ if ( ! selectedMethod ) return ;
69+ await executeMethod ( { deviceKey, methodName : selectedMethod . Name , params : paramValues } ) ;
70+ handleClose ( ) ;
71+ } ;
72+
4873 return (
4974 < >
5075 < h2 > Device Detail</ h2 >
5176 < div className = "h-100 d-flex flex-column overflow-auto" >
5277 < h3 > Properties</ h3 >
53- < ul >
54- { properties . map ( ( p ) => (
55- < li key = { p . Name } >
56- { p . Name } ({ p . Type } ) - Value: { p . Value } - CanRead:{ " " }
57- { p . CanRead ? "Yes" : "No" } - CanWrite: { p . canWrite ? "Yes" : "No" }
58- </ li >
59- ) ) }
60- </ ul >
78+ < table className = "table table-sm table-striped" >
79+ < thead >
80+ < tr >
81+ < th > Name</ th >
82+ < th > Type</ th >
83+ < th > Value</ th >
84+ < th > Can Read</ th >
85+ < th > Can Write</ th >
86+ </ tr >
87+ </ thead >
88+ < tbody >
89+ { properties . map ( ( p ) => (
90+ < tr key = { p . Name } >
91+ < td > { p . Name } </ td >
92+ < td > { p . Type } </ td >
93+ < td > { p . Value } </ td >
94+ < td > { p . CanRead ? "Yes" : "No" } </ td >
95+ < td > { p . canWrite ? "Yes" : "No" } </ td >
96+ </ tr >
97+ ) ) }
98+ </ tbody >
99+ </ table >
61100
62101 < h3 > Methods</ h3 >
63- < ul >
64- { methods . map ( ( m ) => (
65- < li key = { m . Name } >
66- { m . Name } - Params:{ " " }
67- { m . Params . map ( ( param ) => `${ param . Name } : ${ param . Type } ` ) . join (
68- ", " ,
69- ) }
70- </ li >
71- ) ) }
72- </ ul >
102+ < table className = "table table-sm table-striped" >
103+ < thead >
104+ < tr >
105+ < th > Name</ th >
106+ < th > Params</ th >
107+ < th > </ th >
108+ </ tr >
109+ </ thead >
110+ < tbody >
111+ { methods . map ( ( m ) => (
112+ < tr key = { m . Name } >
113+ < td > { m . Name } </ td >
114+ < td >
115+ { m . Params . map ( ( param ) => `${ param . Name } : ${ param . Type } ` ) . join ( ", " ) }
116+ </ td >
117+ < td >
118+ < button className = "btn btn-sm btn-primary" onClick = { ( ) => handleOpen ( m ) } > Execute</ button >
119+ </ td >
120+ </ tr >
121+ ) ) }
122+ </ tbody >
123+ </ table >
124+
125+ < Modal show = { ! ! selectedMethod } onHide = { handleClose } >
126+ < Modal . Header closeButton >
127+ < Modal . Title > Execute: { selectedMethod ?. Name } </ Modal . Title >
128+ </ Modal . Header >
129+ < Modal . Body >
130+ { selectedMethod ?. Params . length === 0 ? (
131+ < p > This method has no parameters.</ p >
132+ ) : (
133+ < Form >
134+ { selectedMethod ?. Params . map ( ( param ) => (
135+ < Form . Group key = { param . Name } className = "mb-3" >
136+ < Form . Label >
137+ { param . Name } < small className = "text-muted" > ({ param . Type } )</ small >
138+ </ Form . Label >
139+ < Form . Control
140+ type = "text"
141+ placeholder = { param . Type }
142+ value = { paramValues [ param . Name ] ?? "" }
143+ onChange = { ( e ) =>
144+ setParamValues ( ( prev ) => ( { ...prev , [ param . Name ] : e . target . value } ) )
145+ }
146+ />
147+ </ Form . Group >
148+ ) ) }
149+ </ Form >
150+ ) }
151+ </ Modal . Body >
152+ < Modal . Footer >
153+ < Button variant = "secondary" onClick = { handleClose } > Cancel</ Button >
154+ < Button variant = "primary" onClick = { handleExecute } disabled = { isExecuting } >
155+ { isExecuting ? "Executing…" : "Execute" }
156+ </ Button >
157+ </ Modal . Footer >
158+ </ Modal >
73159
74160 < h3 > Feedbacks</ h3 >
75161 { feedbacks && (
76162 < >
77163 < h4 > Boolean</ h4 >
78- < ul >
79- { feedbacks . BoolValues . length > 0 ? (
80- < >
81- { feedbacks . BoolValues . map ( ( f ) => (
82- < li key = { f . FeedbackKey } >
83- { f . FeedbackKey } - Value: { f . Value }
84- </ li >
85- ) ) }
86- </ >
87- ) : (
88- < li > None</ li >
89- ) }
90- </ ul >
164+ < table className = "table table-sm table-striped" >
165+ < thead >
166+ < tr >
167+ < th > Key</ th >
168+ < th > Value</ th >
169+ </ tr >
170+ </ thead >
171+ < tbody >
172+ { feedbacks . BoolValues . length > 0 ? (
173+ feedbacks . BoolValues . map ( ( f ) => (
174+ < tr key = { f . FeedbackKey } >
175+ < td > { f . FeedbackKey } </ td >
176+ < td > { String ( f . Value ) } </ td >
177+ </ tr >
178+ ) )
179+ ) : (
180+ < tr > < td colSpan = { 2 } > None</ td > </ tr >
181+ ) }
182+ </ tbody >
183+ </ table >
91184
92185 < h4 > Integer</ h4 >
93- < ul >
94- { feedbacks . IntValues . length > 0 ? (
95- < >
96- { feedbacks . IntValues . map ( ( f ) => (
97- < li key = { f . FeedbackKey } >
98- { f . FeedbackKey } - Value: { f . Value }
99- </ li >
100- ) ) }
101- </ >
102- ) : (
103- < li > None</ li >
104- ) }
105- </ ul >
186+ < table className = "table table-sm table-striped" >
187+ < thead >
188+ < tr >
189+ < th > Key</ th >
190+ < th > Value</ th >
191+ </ tr >
192+ </ thead >
193+ < tbody >
194+ { feedbacks . IntValues . length > 0 ? (
195+ feedbacks . IntValues . map ( ( f ) => (
196+ < tr key = { f . FeedbackKey } >
197+ < td > { f . FeedbackKey } </ td >
198+ < td > { f . Value } </ td >
199+ </ tr >
200+ ) )
201+ ) : (
202+ < tr > < td colSpan = { 2 } > None</ td > </ tr >
203+ ) }
204+ </ tbody >
205+ </ table >
106206
107207 < h4 > Serial</ h4 >
108- < ul >
109- { feedbacks . SerialValues . length > 0 ? (
110- < >
111- { feedbacks . SerialValues . map ( ( f ) => (
112- < li key = { f . FeedbackKey } >
113- { f . FeedbackKey } - Value: { f . Value }
114- </ li >
115- ) ) }
116- </ >
117- ) : (
118- < li > None</ li >
119- ) }
120- </ ul >
208+ < table className = "table table-sm table-striped" >
209+ < thead >
210+ < tr >
211+ < th > Key</ th >
212+ < th > Value</ th >
213+ </ tr >
214+ </ thead >
215+ < tbody >
216+ { feedbacks . SerialValues . length > 0 ? (
217+ feedbacks . SerialValues . map ( ( f ) => (
218+ < tr key = { f . FeedbackKey } >
219+ < td > { f . FeedbackKey } </ td >
220+ < td > { f . Value } </ td >
221+ </ tr >
222+ ) )
223+ ) : (
224+ < tr > < td colSpan = { 2 } > None</ td > </ tr >
225+ ) }
226+ </ tbody >
227+ </ table >
121228 </ >
122229 ) }
123230 </ div >
@@ -129,4 +236,5 @@ interface DeviceDetailRenderProps {
129236 properties : DeviceProperties [ ] ;
130237 methods : DeviceMethods [ ] ;
131238 feedbacks ?: DeviceFeedbacks ;
239+ deviceKey : string ;
132240}
0 commit comments