@@ -12,6 +12,42 @@ import RightPanel from "../commons/RightPanel";
12
12
import SourceFolderSelector from "../../widgets/VideoExplorer/SourceFolderSelector"
13
13
import Frame from "../../widgets/VideoExplorer/Frame"
14
14
15
+ import Slider , { SliderTooltip } from 'rc-slider' ;
16
+
17
+ const createSliderWithTooltip = Slider . createSliderWithTooltip ;
18
+ const Range = createSliderWithTooltip ( Slider . Range ) ;
19
+ const { Handle } = Slider ;
20
+
21
+ const intHandle = props => {
22
+ const { value, dragging, index, ...restProps } = props ;
23
+ return (
24
+ < SliderTooltip
25
+ prefixCls = "rc-slider-tooltip"
26
+ overlay = { value }
27
+ visible = { dragging }
28
+ placement = "top"
29
+ key = { index }
30
+ >
31
+ < Handle value = { value } { ...restProps } />
32
+ </ SliderTooltip >
33
+ ) ;
34
+ } ;
35
+
36
+ const percentHandle = props => {
37
+ const { value, dragging, index, ...restProps } = props ;
38
+ return (
39
+ < SliderTooltip
40
+ prefixCls = "rc-slider-tooltip"
41
+ overlay = { `${ value } %` }
42
+ visible = { dragging }
43
+ placement = "top"
44
+ key = { index }
45
+ >
46
+ < Handle value = { value } { ...restProps } />
47
+ </ SliderTooltip >
48
+ ) ;
49
+ } ;
50
+
15
51
@inject ( "videoExplorerStore" )
16
52
@inject ( "configStore" )
17
53
@inject ( "gpuStore" )
@@ -32,11 +68,14 @@ class MainView extends React.Component {
32
68
cableDistanceFilter : 0 ,
33
69
cableMinNumberFilter : 0 ,
34
70
cableMaxNumberFilter : 4 ,
71
+ isFeedbackSubmitted : false ,
35
72
} ;
36
73
37
74
this . frameRef = React . createRef ( ) ;
38
75
this . feedbackRef = React . createRef ( ) ;
39
76
77
+ this . handleVideoSelection = this . handleVideoSelection . bind ( this )
78
+
40
79
this . onPlayerReady = this . onPlayerReady . bind ( this ) ;
41
80
this . onPlayerProgress = this . onPlayerProgress . bind ( this ) ;
42
81
this . onPlayerPause = this . onPlayerPause . bind ( this ) ;
@@ -46,8 +85,7 @@ class MainView extends React.Component {
46
85
this . toggleAutoScroll = this . toggleAutoScroll . bind ( this ) ;
47
86
48
87
this . handleCableDistanceChange = this . handleCableDistanceChange . bind ( this ) ;
49
- this . handleCableMinNumberChange = this . handleCableMinNumberChange . bind ( this ) ;
50
- this . handleCableMaxNumberChange = this . handleCableMaxNumberChange . bind ( this ) ;
88
+ this . handleCableNumberChange = this . handleCableNumberChange . bind ( this ) ;
51
89
52
90
this . handleFeedbackSubmit = this . handleFeedbackSubmit . bind ( this )
53
91
@@ -87,6 +125,19 @@ class MainView extends React.Component {
87
125
this . setState ( { autoScroll : ! this . state . autoScroll } ) ;
88
126
}
89
127
128
+ handleVideoSelection ( value ) {
129
+ const { videoExplorerStore } = this . props ;
130
+ videoExplorerStore . setVideoPath ( value ) ;
131
+
132
+ // reset state when a video is selected
133
+ this . setState ( {
134
+ currentTime : null ,
135
+ cableDistanceFilter : 0 ,
136
+ cableMinNumberFilter : 0 ,
137
+ cableMaxNumberFilter : 4 ,
138
+ } ) ;
139
+ }
140
+
90
141
onPlayerReady ( ) {
91
142
if ( this . state . currentTime ) {
92
143
this . player . seekTo ( this . state . currentTime , 'seconds' ) ;
@@ -142,16 +193,18 @@ class MainView extends React.Component {
142
193
this . setState ( { currentTime : currentTime } ) ;
143
194
}
144
195
145
- handleCableDistanceChange ( event ) {
146
- this . setState ( { cableDistanceFilter : event . target . value } )
147
- }
196
+ handleCableDistanceChange ( value ) {
197
+ this . setState ( { cableDistanceFilter : value } )
148
198
149
- handleCableMinNumberChange ( event ) {
150
- this . setState ( { cableMinNumberFilter : event . target . value } )
199
+ if ( value > 0 )
200
+ this . setState ( { cableMinNumberFilter : 1 } )
151
201
}
152
202
153
- handleCableMaxNumberChange ( event ) {
154
- this . setState ( { cableMaxNumberFilter : event . target . value } )
203
+ handleCableNumberChange ( values ) {
204
+ this . setState ( {
205
+ cableMinNumberFilter : values [ 0 ] ,
206
+ cableMaxNumberFilter : values [ 1 ]
207
+ } )
155
208
}
156
209
157
210
handleFeedbackSubmit ( event ) {
@@ -161,6 +214,11 @@ class MainView extends React.Component {
161
214
162
215
videoExplorerStore . writeFeedback ( this . feedbackRef . current . value )
163
216
this . feedbackRef . current . value = "" ;
217
+
218
+ this . setState ( { isFeedbackSubmitted : true } ) ;
219
+ setTimeout ( ( ) => {
220
+ this . setState ( { isFeedbackSubmitted : false } ) ;
221
+ } , 2000 ) ;
164
222
}
165
223
166
224
render ( ) {
@@ -218,6 +276,46 @@ class MainView extends React.Component {
218
276
typeof settings . feedbackPath !== 'undefined' &&
219
277
settings . feedbackPath . length > 0 ;
220
278
279
+ const visibleFrames = frames
280
+ . filter ( f => {
281
+
282
+ let visible = typeof f !== undefined ;
283
+
284
+ visible = visible &&
285
+ f . stats &&
286
+ f . stats [ 'cables' ] &&
287
+ f . stats [ 'cables' ] . length >= cableMinNumberFilter &&
288
+ f . stats [ 'cables' ] . length <= cableMaxNumberFilter
289
+
290
+ if (
291
+ cableDistanceFilter > 0 &&
292
+ f . stats &&
293
+ f . stats [ 'cables' ] &&
294
+ f . stats [ 'cables' ] . length > 0
295
+ ) {
296
+ visible = visible &&
297
+ f . stats [ 'cables' ] . some ( c => {
298
+
299
+ // If cable value is inferior to 0
300
+ // - cable on the left position from center
301
+ // - value is visible if inferior to negative cableDistanceFilter
302
+
303
+ // If cable value is superior to 0
304
+ // - cable on the right position from center
305
+ // - value is visible if superior to cableDistanceFilter
306
+
307
+ const value = parseInt ( c * 100 ) ;
308
+
309
+ return value < 0 ?
310
+ value <= 0 - cableDistanceFilter
311
+ :
312
+ value >= cableDistanceFilter
313
+ } )
314
+ }
315
+
316
+ return visible ;
317
+ } )
318
+
221
319
if ( selectedVideo ) {
222
320
223
321
return (
@@ -285,19 +383,27 @@ class MainView extends React.Component {
285
383
< p >
286
384
< a
287
385
href = { `${ selectedVideo . path } ${ selectedFrame . jsonFile } ` }
288
- download = { `${ selectedVideo . name } _{selectedFrame.jsonFile}` }
386
+ download = { `${ selectedVideo . name } _$ {selectedFrame . jsonFile } ` }
289
387
className = "badge badge-secondary"
290
388
>
291
389
< i className = "fas fa-download" /> JSON
292
390
</ a >
293
391
294
392
< a
295
393
href = { `${ selectedVideo . path } ${ selectedFrame . jsonFile . replace ( '.json' , '.png' ) } ` }
296
- download = { `${ selectedVideo . name } _{selectedFrame.jsonFile.replace('.json', '.png')}` }
394
+ download = { `${ selectedVideo . name } _$ {selectedFrame . jsonFile . replace ( '.json' , '.png' ) } ` }
297
395
className = "badge badge-secondary"
298
396
>
299
397
< i className = "fas fa-download" /> Image
300
398
</ a >
399
+
400
+ < a
401
+ href = { `${ selectedVideo . path } ${ settings . folders . bbox_images } ${ selectedFrame . jsonFile . replace ( '.json' , '.png' ) } ` }
402
+ download = { `${ selectedVideo . name } _${ selectedFrame . jsonFile . replace ( '.json' , '_bbox.png' ) } ` }
403
+ className = "badge badge-secondary"
404
+ >
405
+ < i className = "fas fa-download" /> Image with bounding-boxes
406
+ </ a >
301
407
</ p >
302
408
< SyntaxHighlighter
303
409
language = { "json" }
@@ -318,9 +424,9 @@ class MainView extends React.Component {
318
424
>
319
425
< div className = "form-group" >
320
426
< label
321
- for = "feedbackTextArea"
427
+ htmlFor = "feedbackTextArea"
322
428
>
323
- Leave a feedback about this frame:
429
+ Leave a feedback on frame { selectedFrame . index } :
324
430
</ label >
325
431
< textarea
326
432
className = "form-control"
@@ -334,6 +440,11 @@ class MainView extends React.Component {
334
440
>
335
441
Send feedback
336
442
</ button >
443
+ { this . state . isFeedbackSubmitted ?
444
+ < span > Feedback has been submitted</ span >
445
+ :
446
+ null
447
+ }
337
448
</ div >
338
449
</ form >
339
450
</ div >
@@ -352,59 +463,58 @@ class MainView extends React.Component {
352
463
< div className = "d-flex" >
353
464
< form >
354
465
< div className = "form-group row" >
355
- < legend className = "col-form-label col-4" > Number of Cables</ legend >
356
- < div className = "col-4" >
357
- < input
358
- id = "cableMinNumberFilter"
359
- type = "number"
360
- className = "form-control"
361
- onChange = { this . handleCableMinNumberChange }
362
- value = { this . state . cableMinNumberFilter }
363
- />
364
- < label
365
- for = "cableMinNumberFilter"
366
- className = "col-form-label"
367
- >
368
- Min
369
- </ label >
370
- </ div >
371
- < div className = "col-4" >
372
- < input
373
- id = "cableMaxNumberFilter"
374
- className = "form-control"
375
- type = "number"
376
- onChange = { this . handleCableMaxNumberChange }
377
- value = { this . state . cableMaxNumberFilter }
378
- />
379
- < label
380
- for = "cableMaxNumberFilter"
381
- className = "col-form-label"
382
- >
383
- Max
384
- </ label >
385
- </ div >
466
+ < legend className = "col-form-label" > Number of Cables</ legend >
467
+ < br />
468
+ < Range
469
+ handle = { intHandle }
470
+ min = { 0 }
471
+ max = { 4 }
472
+ defaultValue = { [
473
+ this . state . cableMinNumberFilter ,
474
+ this . state . cableMaxNumberFilter
475
+ ] }
476
+ onAfterChange = { this . handleCableNumberChange }
477
+ />
386
478
</ div >
387
479
< div className = "form-group row" >
388
- < legend className = "col-form-label col-4" > Exclude cable distance from center</ legend >
389
- < div class = "col-8" >
390
- < input
391
- id = "cableDistanceFilter"
392
- type = "number"
393
- className = "form-control"
394
- onChange = { this . handleCableDistanceChange }
395
- value = { this . state . cableDistanceFilter }
396
- />
397
- </ div >
480
+ < legend className = "col-form-label" > Exclude cable distance from center</ legend >
481
+ < br />
482
+ < Slider
483
+ id = "cableDistanceFilter"
484
+ handle = { percentHandle }
485
+ onAfterChange = { this . handleCableDistanceChange }
486
+ />
398
487
</ div >
399
488
</ form >
400
489
</ div >
401
490
402
- < div className = "toggleAutoScroll d-flex justify-content-end" >
403
- Auto-scroll frames
404
- < input
405
- type = "checkbox"
406
- onChange = { this . toggleAutoScroll }
407
- checked = { this . state . autoScroll } />
491
+ < div className = "row" >
492
+ < div className = "col" >
493
+ Frames { visibleFrames . length } / { frames . length }
494
+ </ div >
495
+ < div
496
+ id = "autoScrollToggle"
497
+ className = "col"
498
+ >
499
+ < form className = "form-inline" >
500
+ < div className = "form-check" >
501
+ < legend
502
+ className = "form-check-label"
503
+ htmlFor = "autoScrollCheckbox"
504
+ style = { { "font-size" : "unset" } }
505
+ >
506
+ Autoscroll frames
507
+ </ legend >
508
+ < input
509
+ id = "autoScrollCheckbox"
510
+ type = "checkbox"
511
+ className = "form-check-input"
512
+ onChange = { this . toggleAutoScroll }
513
+ checked = { this . state . autoScroll }
514
+ />
515
+ </ div >
516
+ </ form >
517
+ </ div >
408
518
</ div >
409
519
410
520
< div className = 'video-chrono' >
@@ -417,46 +527,7 @@ class MainView extends React.Component {
417
527
: null
418
528
}
419
529
{
420
- frames
421
- . filter ( f => {
422
-
423
- let visible = typeof f !== undefined ;
424
-
425
- visible = visible &&
426
- f . stats &&
427
- f . stats [ 'cables' ] &&
428
- f . stats [ 'cables' ] . length >= cableMinNumberFilter &&
429
- f . stats [ 'cables' ] . length <= cableMaxNumberFilter
430
-
431
- if (
432
- cableDistanceFilter > 0 &&
433
- f . stats &&
434
- f . stats [ 'cables' ] &&
435
- f . stats [ 'cables' ] . length > 0
436
- ) {
437
- visible = visible &&
438
- f . stats [ 'cables' ] . some ( c => {
439
-
440
- // If cable value is inferior to 0
441
- // - cable on the left position from center
442
- // - value is visible if inferior to negative cableDistanceFilter
443
-
444
- // If cable value is superior to 0
445
- // - cable on the right position from center
446
- // - value is visible if superior to cableDistanceFilter
447
-
448
- const value = parseInt ( c * 100 ) ;
449
-
450
- return value < 0 ?
451
- value <= 0 - cableDistanceFilter
452
- :
453
- value >= cableDistanceFilter
454
- } )
455
- }
456
-
457
- return visible ;
458
- } )
459
- . map ( f =>
530
+ visibleFrames . map ( f =>
460
531
< div
461
532
key = { f . id }
462
533
className = "scrollFrame"
@@ -487,7 +558,9 @@ class MainView extends React.Component {
487
558
< div className = { mainClassNames . join ( " " ) } >
488
559
< div className = "container-fluid" >
489
560
< div className = "content" >
490
- < SourceFolderSelector />
561
+ < SourceFolderSelector
562
+ handleVideoSelection = { this . handleVideoSelection }
563
+ />
491
564
< RightPanel />
492
565
</ div >
493
566
</ div >
0 commit comments