1
- import React , { Component } from 'react' ;
2
- import { Typography , Box , List , ListItem , ListItemText } from '@material-ui/core' ;
3
- import { SectionContent } from '../components' ;
1
+ import React , { Component } from 'react' ;
2
+ import { Typography , Grid , Card , CardContent , createStyles , WithStyles , Theme , withStyles } from '@material-ui/core' ;
3
+ import { WebSocketControllerProps , SectionContent , webSocketController } from '../components' ;
4
4
5
- class DemoInformation extends Component {
5
+ import { WEB_SOCKET_ROOT } from '../api' ;
6
+ // import { Time } from '../ntp/types';
7
+
8
+
9
+ export const SENSOR_VALUE_WEBSOCKET_URL = WEB_SOCKET_ROOT + "sensorValue" ;
10
+
11
+ function compareSensorValues ( a : SensorValue , b : SensorValue ) {
12
+ if ( a . name < b . name ) {
13
+ return - 1 ;
14
+ }
15
+ if ( a . name > b . name ) {
16
+ return 1 ;
17
+ }
18
+ return 0 ;
19
+ }
20
+
21
+ export interface SensorValue {
22
+ name : string ,
23
+ val : number ,
24
+ ts : number ,
25
+ classStyle : string ,
26
+ resetAnim : boolean ,
27
+ animSet : ( ) => void
28
+ }
29
+
30
+ export interface IState {
31
+ sens : SensorValue [ ] ,
32
+ }
33
+
34
+ const mystyles = ( theme : Theme ) => createStyles (
35
+ {
36
+ "off" : { color :"red" } ,
37
+ "animation_trigger" : {
38
+ "animation-name" : `$animateElement` ,
39
+ "animation-duration" : "0.1s" ,
40
+ } ,
41
+
42
+ "@keyframes animateElement" : {
43
+ "0%" : { "background-color" : "red" } ,
44
+ "25%" : { "background-color" : "yellow" } ,
45
+ "50%" : { "background-color" : "blue" } ,
46
+ "100%" : { "background-color" : "green" } ,
47
+ }
48
+ }
49
+ ) ;
50
+
51
+
52
+
53
+ type DemoInformationProps = WithStyles < typeof mystyles > & WebSocketControllerProps < SensorValue > ;
54
+
55
+ class DemoInformation extends Component < DemoInformationProps , IState > {
56
+ constructor ( props : DemoInformationProps ) {
57
+ super ( props ) ;
58
+ this . state = {
59
+ sens : [ ]
60
+ }
61
+ }
62
+
63
+ resetAnim = ( ( ) => {
64
+ var sensorlist :SensorValue [ ] = [ ] ;
65
+ this . state . sens . forEach ( ( sensor : SensorValue ) => {
66
+ if ( sensor . resetAnim ) {
67
+ sensor . classStyle = this . props . classes . off ;
68
+ }
69
+ sensorlist . push ( sensor ) ;
70
+ } )
71
+ this . setState ( { sens :sensorlist } )
72
+ } ) ;
73
+
74
+
75
+ updateSensorList = ( sensor : SensorValue ) => {
76
+ const sensors = this . state . sens ! . filter ( u => u . name !== sensor . name ) ;
77
+ sensor . classStyle = this . props . classes . animation_trigger ;
78
+ sensor . resetAnim = true ;
79
+ if ( sensors . length === this . state . sens ! . length ) {
80
+ this . props . enqueueSnackbar ( "New sensor reporting: " + sensor . name , {
81
+ variant : 'success' ,
82
+ } ) ;
83
+ }
84
+ sensors . push ( sensor ) ;
85
+ this . setState ( { sens : sensors } ) ;
86
+ }
87
+
88
+ componentDidUpdate ( prevProps : DemoInformationProps ) {
89
+ if ( prevProps . data !== undefined && ( prevProps . data ! . val !== this . props . data ?. val || prevProps . data ! . name !== this . props . data ! . name ) ) {
90
+ // console.log("update ",prevProps.data, this.props.data)
91
+ this . updateSensorList ( this . props . data ! )
92
+ }
93
+ }
6
94
7
95
render ( ) {
8
96
return (
@@ -16,62 +104,45 @@ class DemoInformation extends Component {
16
104
This serves to isolate your project code from the from the rest of the user interface which should
17
105
simplify merges should you wish to update your project with future framework changes.
18
106
</ Typography >
19
- < Typography variant = "body1" paragraph >
20
- The demo project interface code is stored in the 'interface/src/project' directory:
21
- </ Typography >
22
- < List >
23
- < ListItem >
24
- < ListItemText
25
- primary = "ProjectMenu.tsx"
26
- secondary = "You can add your project's screens to the side bar here."
27
- />
28
- </ ListItem >
29
- < ListItem >
30
- < ListItemText
31
- primary = "ProjectRouting.tsx"
32
- secondary = "The routing which controls the screens of your project."
33
- />
34
- </ ListItem >
35
- < ListItem >
36
- < ListItemText
37
- primary = "DemoProject.tsx"
38
- secondary = "This screen, with tabs and tab routing."
39
- />
40
- </ ListItem >
41
- < ListItem >
42
- < ListItemText
43
- primary = "DemoInformation.tsx"
44
- secondary = "The demo information page."
45
- />
46
- </ ListItem >
47
- < ListItem >
48
- < ListItemText
49
- primary = "LightStateRestController.tsx"
50
- secondary = "A form which lets the user control the LED over a REST service."
51
- />
52
- </ ListItem >
53
- < ListItem >
54
- < ListItemText
55
- primary = "LightStateWebSocketController.tsx"
56
- secondary = "A form which lets the user control and monitor the status of the LED over WebSockets."
57
- />
58
- </ ListItem >
59
- < ListItem >
60
- < ListItemText
61
- primary = "LightMqttSettingsController.tsx"
62
- secondary = "A form which lets the user change the MQTT settings for MQTT based control of the LED."
63
- />
64
- </ ListItem >
65
- </ List >
66
- < Box mt = { 2 } >
67
- < Typography variant = "body1" >
68
- See the project < a href = "https://github.com/rjwats/esp8266-react/" > README</ a > for a full description of the demo project.
69
- </ Typography >
70
- </ Box >
107
+ < SectionContent title = 'Live sensor values' titleGutter >
108
+ < Grid container spacing = { 1 } >
109
+ {
110
+ this . state . sens ! . sort ( compareSensorValues ) . map ( sensor => (
111
+ < SensorValueForm { ...sensor } key = { sensor . name } animSet = { this . resetAnim } />
112
+ ) )
113
+ }
114
+ </ Grid >
115
+ </ SectionContent >
116
+
117
+
71
118
</ SectionContent >
72
119
)
73
120
}
74
121
75
122
}
123
+ export default withStyles ( mystyles ) ( webSocketController ( SENSOR_VALUE_WEBSOCKET_URL , 100 , DemoInformation ) ) ;
76
124
77
- export default DemoInformation ;
125
+ // export default DemoInformation;
126
+
127
+
128
+ class SensorValueForm extends Component < SensorValue > {
129
+
130
+ render ( ) {
131
+ const { val, name, classStyle, animSet } = this . props ;
132
+ return (
133
+ < Grid item xs = { 12 } sm = { 4 } >
134
+ < Card >
135
+ < CardContent >
136
+ < Typography gutterBottom variant = "h5" component = "h2" >
137
+ { name }
138
+ </ Typography >
139
+ < Typography variant = "body2" component = "p" >
140
+ Latest value:
141
+ </ Typography >
142
+ < Typography variant = "h5" className = { classStyle } onAnimationEnd = { animSet } > { val } </ Typography >
143
+ </ CardContent >
144
+ </ Card >
145
+ </ Grid >
146
+ )
147
+ }
148
+ }
0 commit comments