1- import React , { useCallback , useEffect , useState , useContext } from ' react' ;
1+ import React , { useCallback , useEffect , useState , useContext } from " react" ;
22import { Button , Box , LinearProgress , Tooltip } from "@mui/material" ;
33import { GenericModal } from "../ui/GenericModal" ;
44import { stopRecording } from "../../api/recording" ;
55import { useGlobalInfoStore } from "../../context/globalInfo" ;
6- import { AuthContext } from ' ../../context/auth' ;
6+ import { AuthContext } from " ../../context/auth" ;
77import { useSocketStore } from "../../context/socket" ;
88import { TextField , Typography } from "@mui/material" ;
99import { WarningText } from "../ui/texts" ;
1010import NotificationImportantIcon from "@mui/icons-material/NotificationImportant" ;
11- import { useNavigate } from ' react-router-dom' ;
12- import { useTranslation } from ' react-i18next' ;
11+ import { useNavigate } from " react-router-dom" ;
12+ import { useTranslation } from " react-i18next" ;
1313
1414interface SaveRecordingProps {
1515 fileName : string ;
@@ -20,10 +20,19 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => {
2020 const [ openModal , setOpenModal ] = useState < boolean > ( false ) ;
2121 const [ needConfirm , setNeedConfirm ] = useState < boolean > ( false ) ;
2222 const [ saveRecordingName , setSaveRecordingName ] = useState < string > ( fileName ) ;
23- const [ saveRecordingDescription , setSaveRecordingDescription ] = useState < string > ( "" ) ;
23+ const [ saveRecordingDescription , setSaveRecordingDescription ] =
24+ useState < string > ( "" ) ;
2425 const [ waitingForSave , setWaitingForSave ] = useState < boolean > ( false ) ;
2526
26- const { browserId, setBrowserId, notify, recordings, isLogin, recordingName, retrainRobotId } = useGlobalInfoStore ( ) ;
27+ const {
28+ browserId,
29+ setBrowserId,
30+ notify,
31+ recordings,
32+ isLogin,
33+ recordingName,
34+ retrainRobotId,
35+ } = useGlobalInfoStore ( ) ;
2736 const { socket } = useSocketStore ( ) ;
2837 const { state, dispatch } = useContext ( AuthContext ) ;
2938 const { user } = state ;
@@ -41,17 +50,21 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => {
4150 setNeedConfirm ( false ) ;
4251 }
4352 setSaveRecordingName ( value ) ;
44- }
53+ } ;
4554
46- const handleChangeOfDescription = ( event : React . ChangeEvent < HTMLInputElement > ) => {
55+ const handleChangeOfDescription = (
56+ event : React . ChangeEvent < HTMLInputElement >
57+ ) => {
4758 const { value } = event . target ;
4859 setSaveRecordingDescription ( value ) ;
49- }
60+ } ;
5061
5162 const handleSaveRecording = async ( event : React . SyntheticEvent ) => {
5263 event . preventDefault ( ) ;
5364 if ( recordings . includes ( saveRecordingName ) ) {
54- if ( needConfirm ) { return ; }
65+ if ( needConfirm ) {
66+ return ;
67+ }
5568 setNeedConfirm ( true ) ;
5669 } else {
5770 await saveRecording ( ) ;
@@ -66,71 +79,84 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => {
6679 }
6780 } ;
6881
69- const exitRecording = useCallback ( async ( data ?: { actionType : string } ) => {
70- let successMessage = t ( 'save_recording.notifications.save_success' ) ;
71-
72- if ( data && data . actionType ) {
73- if ( data . actionType === 'retrained' ) {
74- successMessage = t ( 'save_recording.notifications.retrain_success' ) ;
75- } else if ( data . actionType === 'saved' ) {
76- successMessage = t ( 'save_recording.notifications.save_success' ) ;
77- } else if ( data . actionType === 'error' ) {
78- successMessage = t ( 'save_recording.notifications.save_error' ) ;
82+ const exitRecording = useCallback (
83+ async ( data ?: { actionType : string } ) => {
84+ let successMessage = t ( "save_recording.notifications.save_success" ) ;
85+
86+ if ( data && data . actionType ) {
87+ if ( data . actionType === "retrained" ) {
88+ successMessage = t ( "save_recording.notifications.retrain_success" ) ;
89+ } else if ( data . actionType === "saved" ) {
90+ successMessage = t ( "save_recording.notifications.save_success" ) ;
91+ } else if ( data . actionType === "error" ) {
92+ successMessage = t ( "save_recording.notifications.save_error" ) ;
93+ }
7994 }
80- }
81-
82- const notificationData = {
83- type : 'success' ,
84- message : successMessage ,
85- timestamp : Date . now ( )
86- } ;
87-
88- if ( window . opener ) {
89- window . opener . postMessage ( {
90- type : 'recording-notification' ,
91- notification : notificationData
92- } , '*' ) ;
93-
94- window . opener . postMessage ( {
95- type : 'session-data-clear' ,
96- timestamp : Date . now ( )
97- } , '*' ) ;
98- }
99-
100- if ( browserId ) {
101- await stopRecording ( browserId ) ;
102- }
103- setBrowserId ( null ) ;
104-
105- window . close ( ) ;
106- } , [ setBrowserId , browserId , t ] ) ;
95+
96+ const notificationData = {
97+ type : "success" ,
98+ message : successMessage ,
99+ timestamp : Date . now ( ) ,
100+ } ;
101+
102+ if ( window . opener ) {
103+ window . opener . postMessage (
104+ {
105+ type : "recording-notification" ,
106+ notification : notificationData ,
107+ } ,
108+ "*"
109+ ) ;
110+
111+ window . opener . postMessage (
112+ {
113+ type : "session-data-clear" ,
114+ timestamp : Date . now ( ) ,
115+ } ,
116+ "*"
117+ ) ;
118+ }
119+
120+ if ( browserId ) {
121+ await stopRecording ( browserId ) ;
122+ }
123+ setBrowserId ( null ) ;
124+
125+ window . close ( ) ;
126+ } ,
127+ [ setBrowserId , browserId , t ]
128+ ) ;
107129
108130 // notifies backed to save the recording in progress,
109131 // releases resources and changes the view for main page by clearing the global browserId
110132 const saveRecording = async ( ) => {
111133 if ( user ) {
112- const payload = {
113- fileName : saveRecordingName || recordingName ,
114- userId : user . id ,
134+ const payload = {
135+ fileName : saveRecordingName || recordingName ,
136+ userId : user . id ,
115137 isLogin : isLogin ,
116138 robotId : retrainRobotId ,
117139 description : saveRecordingDescription ,
118140 } ;
119141
120- console . log ( payload )
121- socket ?. emit ( ' save' , payload ) ;
142+ console . log ( payload ) ;
143+ socket ?. emit ( " save" , payload ) ;
122144 setWaitingForSave ( true ) ;
123- console . log ( `Saving the recording as ${ saveRecordingName || recordingName } for userId ${ user . id } with description: ${ saveRecordingDescription } ` ) ;
145+ console . log (
146+ `Saving the recording as ${
147+ saveRecordingName || recordingName
148+ } for userId ${ user . id } with description: ${ saveRecordingDescription } `
149+ ) ;
124150 } else {
125- console . error ( t ( ' save_recording.notifications.user_not_logged' ) ) ;
151+ console . error ( t ( " save_recording.notifications.user_not_logged" ) ) ;
126152 }
127153 } ;
128154
129155 useEffect ( ( ) => {
130- socket ?. on ( ' fileSaved' , exitRecording ) ;
156+ socket ?. on ( " fileSaved" , exitRecording ) ;
131157 return ( ) => {
132- socket ?. off ( ' fileSaved' , exitRecording ) ;
133- }
158+ socket ?. off ( " fileSaved" , exitRecording ) ;
159+ } ;
134160 } , [ socket , exitRecording ] ) ;
135161
136162 return (
@@ -140,74 +166,112 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => {
140166 variant = "outlined"
141167 color = "success"
142168 sx = { {
143- marginRight : ' 20px' ,
144- color : ' #00c853 !important' ,
145- borderColor : ' #00c853 !important' ,
146- backgroundColor : ' whitesmoke !important' ,
169+ marginRight : " 20px" ,
170+ color : " #00c853 !important" ,
171+ borderColor : " #00c853 !important" ,
172+ backgroundColor : " whitesmoke !important" ,
147173 } }
148174 size = "small"
149175 >
150- { t ( ' right_panel.buttons.finish' ) }
176+ { t ( " right_panel.buttons.finish" ) }
151177 </ Button >
152178
153- < GenericModal isOpen = { openModal } onClose = { ( ) => setOpenModal ( false ) } modalStyle = { modalStyle } >
154- < form onSubmit = { handleSaveRecording } style = { { display : 'flex' , flexDirection : 'column' , alignItems : 'flex-start' } } >
155- < Typography variant = "h6" > { t ( 'save_recording.title' ) } </ Typography >
179+ < GenericModal
180+ isOpen = { openModal }
181+ onClose = { ( ) => setOpenModal ( false ) }
182+ modalStyle = { modalStyle }
183+ >
184+ < form
185+ onSubmit = { handleSaveRecording }
186+ style = { {
187+ display : "flex" ,
188+ flexDirection : "column" ,
189+ alignItems : "flex-start" ,
190+ } }
191+ >
192+ < Typography variant = "h6" > { t ( "save_recording.title" ) } </ Typography >
156193 < TextField
157194 required
158- sx = { { width : ' 300px' , margin : ' 15px 0px' } }
195+ sx = { { width : " 300px" , margin : " 15px 0px" } }
159196 onChange = { handleChangeOfTitle }
160197 id = "title"
161- label = { t ( ' save_recording.robot_name' ) }
198+ label = { t ( " save_recording.robot_name" ) }
162199 variant = "outlined"
163200 value = { saveRecordingName }
164201 />
165202 < TextField
166- sx = { { width : '300px' , margin : '15px 0px' } }
167- onChange = { handleChangeOfDescription }
203+ sx = { { width : "300px" , margin : "15px 0px" } }
204+ onChange = { ( e ) =>
205+ setSaveRecordingDescription ( e . target . value . slice ( 0 , 50 ) )
206+ }
168207 id = "description"
169- label = { t ( ' save_recording.description' ) }
208+ label = { t ( " save_recording.description" ) }
170209 variant = "outlined"
171210 value = { saveRecordingDescription }
172211 multiline
173212 rows = { 2 }
213+ inputProps = { { maxLength : 50 } }
214+ helperText = {
215+ < span
216+ style = { {
217+ color :
218+ 50 - saveRecordingDescription . length <= 0
219+ ? "red"
220+ : "inherit" ,
221+ } }
222+ >
223+ { 50 - saveRecordingDescription . length } characters remaining
224+ </ span >
225+ }
174226 />
175- { needConfirm
176- ?
177- ( < React . Fragment >
178- < Button color = "error" variant = "contained" onClick = { saveRecording } sx = { { marginTop : '10px' } } >
179- { t ( 'save_recording.buttons.confirm' ) }
227+ { needConfirm ? (
228+ < React . Fragment >
229+ < Button
230+ color = "error"
231+ variant = "contained"
232+ onClick = { saveRecording }
233+ sx = { { marginTop : "10px" } }
234+ >
235+ { t ( "save_recording.buttons.confirm" ) }
180236 </ Button >
181237 < WarningText >
182238 < NotificationImportantIcon color = "warning" />
183- { t ( ' save_recording.errors.exists_warning' ) }
239+ { t ( " save_recording.errors.exists_warning" ) }
184240 </ WarningText >
185- </ React . Fragment > )
186- : < Button type = "submit" variant = "contained" sx = { { marginTop : '10px' } } >
187- { t ( 'save_recording.buttons.save' ) }
241+ </ React . Fragment >
242+ ) : (
243+ < Button
244+ type = "submit"
245+ variant = "contained"
246+ sx = { { marginTop : "10px" } }
247+ >
248+ { t ( "save_recording.buttons.save" ) }
188249 </ Button >
189- }
190- { waitingForSave &&
191- < Tooltip title = { t ( 'save_recording.tooltips.optimizing' ) } placement = { "bottom" } >
192- < Box sx = { { width : '100%' , marginTop : '10px' } } >
250+ ) }
251+ { waitingForSave && (
252+ < Tooltip
253+ title = { t ( "save_recording.tooltips.optimizing" ) }
254+ placement = { "bottom" }
255+ >
256+ < Box sx = { { width : "100%" , marginTop : "10px" } } >
193257 < LinearProgress />
194258 </ Box >
195259 </ Tooltip >
196- }
260+ ) }
197261 </ form >
198262 </ GenericModal >
199263 </ div >
200264 ) ;
201- }
265+ } ;
202266
203267const modalStyle = {
204- top : ' 25%' ,
205- left : ' 50%' ,
206- transform : ' translate(-50%, -50%)' ,
207- width : ' 30%' ,
208- backgroundColor : ' background.paper' ,
268+ top : " 25%" ,
269+ left : " 50%" ,
270+ transform : " translate(-50%, -50%)" ,
271+ width : " 30%" ,
272+ backgroundColor : " background.paper" ,
209273 p : 4 ,
210- height : ' fit-content' ,
211- display : ' block' ,
212- padding : ' 20px' ,
213- } ;
274+ height : " fit-content" ,
275+ display : " block" ,
276+ padding : " 20px" ,
277+ } ;
0 commit comments