@@ -2,7 +2,8 @@ import React, { Component, Fragment } from 'react';
2
2
import moment from 'moment' ;
3
3
4
4
import { WithTheme , withTheme } from '@material-ui/core/styles' ;
5
- import { Avatar , Divider , List , ListItem , ListItemAvatar , ListItemText } from '@material-ui/core' ;
5
+ import { Avatar , Divider , List , ListItem , ListItemAvatar , ListItemText , Button } from '@material-ui/core' ;
6
+ import { Dialog , DialogTitle , DialogContent , DialogActions , Box , TextField } from '@material-ui/core' ;
6
7
7
8
import SwapVerticalCircleIcon from '@material-ui/icons/SwapVerticalCircle' ;
8
9
import AccessTimeIcon from '@material-ui/icons/AccessTime' ;
@@ -11,18 +12,116 @@ import UpdateIcon from '@material-ui/icons/Update';
11
12
import AvTimerIcon from '@material-ui/icons/AvTimer' ;
12
13
import RefreshIcon from '@material-ui/icons/Refresh' ;
13
14
14
- import { Res
1E11
tFormProps , FormActions , FormButton , HighlightAvatar } from '../components' ;
15
-
15
+ import { RestFormProps , FormButton , HighlightAvatar } from '../components' ;
16
16
import { isNtpActive , ntpStatusHighlight , ntpStatus } from './NTPStatus' ;
17
- import { formatIsoDateTime } from './TimeFormat' ;
18
- import { NTPStatus } from './types' ;
17
+ import { formatIsoDateTime , formatLocalDateTime } from './TimeFormat' ;
18
+ import { NTPStatus , Time } from './types' ;
19
+ import { redirectingAuthorizedFetch , withAuthenticatedContext , AuthenticatedContextProps } from '../authentication' ;
20
+ import { TIME_ENDPOINT } from '../api' ;
21
+
22
+ type NTPStatusFormProps = RestFormProps < NTPStatus > & WithTheme & AuthenticatedContextProps ;
19
23
20
- type NTPStatusFormProps = RestFormProps < NTPStatus > & WithTheme ;
24
+ interface NTPStatusFormState {
25
+ settingTime : boolean ;
26
+ localTime : string ;
27
+ processing : boolean ;
28
+ }
21
29
22
- class NTPStatusForm extends Component < NTPStatusFormProps > {
30
+ class NTPStatusForm extends Component < NTPStatusFormProps , NTPStatusFormState > {
31
+
32
+ constructor ( props : NTPStatusFormProps ) {
33
+ super ( props ) ;
34
+ this . state = {
35
+ settingTime : false ,
36
+ localTime : '' ,
37
+ processing : false
38
+ } ;
39
+ }
40
+
41
+ updateLocalTime = ( event : React . ChangeEvent < HTMLInputElement > ) => {
42
+ this . setState ( { localTime : event . target . value } ) ;
43
+ }
44
+
45
+ openSetTime = ( ) => {
46
+ this . setState ( { localTime : formatLocalDateTime ( moment ( ) ) , settingTime : true , } ) ;
47
+ }
48
+
49
+ closeSetTime = ( ) => {
50
+ this . setState ( { settingTime : false } ) ;
51
+ }
52
+
53
+ createAdjustedTime = ( ) : Time => {
54
+ const currentLocalTime = moment ( this . props . data . time_local ) ;
55
+ const newLocalTime = moment ( this . state . localTime ) ;
56
+ newLocalTime . subtract ( currentLocalTime . utcOffset ( ) )
57
+ newLocalTime . milliseconds ( 0 ) ;
58
+ newLocalTime . utc ( ) ;
59
+ return {
60
+ time_utc : newLocalTime . format ( )
61
+ }
62
+ }
63
+
64
+ configureTime = ( ) => {
65
+ this . setState ( { processing : true } ) ;
66
+ redirectingAuthorizedFetch ( TIME_ENDPOINT ,
67
+ {
68
+ method : 'POST' ,
69
+ body : JSON . stringify ( this . createAdjustedTime ( ) ) ,
70
+ headers : {
71
+ 'Content-Type' : 'application/json'
72
+ }
73
+ } )
74
+ . then ( response => {
75
+ if ( response . status === 200 ) {
76
+ this . props . enqueueSnackbar ( "Time set successfully" , { variant : 'success' } ) ;
77
+ this . setState ( { processing : false , settingTime : false } , this . props . loadData ) ;
78
+ } else {
79
+ throw Error ( "Error setting time, status code: " + response . status ) ;
80
+ }
81
+ } )
82
+ . catch ( error => {
83
+ this . props . enqueueSnackbar ( error . message || "Problem setting the time" , { variant : 'error' } ) ;
84
+ this . setState ( { processing : false , settingTime : false } ) ;
85
+ } ) ;
86
+ }
87
+
88
+ renderSetTimeDialog ( ) {
89
+ return (
90
+ < Dialog
91
+ open = { this . state . settingTime }
92
+ onClose = { this . closeSetTime }
93
+ >
94
+ < DialogTitle > Set Time</ DialogTitle >
95
+ < DialogContent dividers >
96
+ < Box mb = { 2 } > Enter local date and time below to set the device's time.</ Box >
97
+ < TextField
98
+ label = "Local Time"
99
+ type = "datetime-local"
100
+ value = { this . state . localTime }
101
+ onChange = { this . updateLocalTime }
102
+ disabled = { this . state . processing }
103
+ variant = "outlined"
104
+ fullWidth
105
+ InputLabelProps = { {
106
+ shrink : true ,
107
+ } }
108
+ />
109
+ </ DialogContent >
110
+ < DialogActions >
111
+ < Button variant = "contained" onClick = { this . closeSetTime } color = "secondary" >
112
+ Cancel
113
+ </ Button >
114
+ < Button startIcon = { < AccessTimeIcon /> } variant = "contained" onClick = { this . configureTime } disabled = { this . state . processing } color = "primary" autoFocus >
115
+ Set Time
116
+ </ Button >
117
+ </ DialogActions >
118
+ </ Dialog >
119
+ )
120
+ }
23
121
24
122
render ( ) {
25
123
const { data, theme } = this . props
124
+ const me = this . props . authenticatedContext . me ;
26
125
return (
27
126
< Fragment >
28
127
< List >
@@ -40,30 +139,30 @@ class NTPStatusForm extends Component<NTPStatusFormProps> {
40
139
< ListItem >
41
140
< ListItemAvatar >
42
141
< Avatar >
43
- < AccessTimeIcon />
44
- </ Avatar >
45
- </ ListItemAvatar >
46
- < ListItemText primary = "Local Time" secondary = { formatIsoDateTime ( data . time_local ) } />
47
- </ ListItem >
48
- < Divider variant = "inset" component = "li" />
49
- < ListItem >
50
- < ListItemAvatar >
51
- < Avatar >
52
- < SwapVerticalCircleIcon />
142
+ < DNSIcon />
53
143
</ Avatar >
54
144
</ ListItemAvatar >
55
- < ListItemText primary = "UTC Time " secondary = { formatIsoDateTime ( data . time_utc ) } />
145
+ < ListItemText primary = "NTP Server " secondary = { data . server } />
56
146
</ ListItem >
57
147
< Divider variant = "inset" component = "li" />
58
148
</ Fragment >
59
149
) }
60
150
< ListItem >
61
151
< ListItemAvatar >
62
152
< Avatar >
63
- < DNSIcon />
153
+ < AccessTimeIcon />
64
154
</ Avatar >
65
155
</ ListItemAvatar >
66
- < ListItemText primary = "NTP Server" secondary = { data . server } />
156
+ < ListItemText primary = "Local Time" secondary = { formatIsoDateTime ( data . time_local ) } />
157
+ </ ListItem >
158
+ < Divider variant = "inset" component = "li" />
159
+ < ListItem >
160
+ < ListItemAvatar >
161
+ < Avatar >
162
+ < SwapVerticalCircleIcon />
163
+ </ Avatar >
164
+ </ ListItemAvatar >
165
+ < ListItemText primary = "UTC Time" secondary = { formatIsoDateTime ( data . time_utc ) } />
67
166
</ ListItem >
68
167
< Divider variant = "inset" component = "li" />
69
168
< ListItem >
@@ -76,14 +175,24 @@ class NTPStatusForm extends Component<NTPStatusFormProps> {
76
175
</ ListItem >
77
176
< Divider variant = "inset" component = "li" />
78
177
</ List >
79
- < FormActions >
80
- < FormButton startIcon = { < RefreshIcon /> } variant = "contained" color = "secondary" onClick = { this . props . loadData } >
81
- Refresh
82
- </ FormButton >
83
- </ FormActions >
178
+ < Box display = "flex" flexWrap = "wrap" >
179
+ < Box flexGrow = { 1 } padding = { 1 } >
180
+ < FormButton startIcon = { < RefreshIcon /> } variant = "contained" color = "secondary" onClick = { this . props . loadData } >
181
+ Refresh
182
+ </ FormButton >
183
+ </ Box >
184
+ { me . admin && ! isNtpActive ( data ) && (
185
+ < Box flexWrap = "none" padding = { 1 } whiteSpace = "nowrap" >
186
+ < Button onClick = { this . openSetTime } variant = "contained" color = "primary" startIcon = { < AccessTimeIcon /> } >
187
+ Set Time
188
+ </ Button >
189
+ </ Box >
190
+ ) }
191
+ </ Box >
192
+ { this . renderSetTimeDialog ( ) }
84
193
</ Fragment >
85
194
) ;
86
195
}
87
196
}
88
197
89
- export default withTheme ( NTPStatusForm ) ;
198
+ export default withAuthenticatedContext ( withTheme ( NTPStatusForm ) ) ;
0 commit comments