Skip to content

Commit

Permalink
Refactored upload modal to seperate component
Browse files Browse the repository at this point in the history
Refactored nav bar to pass data to upload modal
Refactored upload modal to have restrictions on frame rate changes
Limited framerate changes to uploading only
  • Loading branch information
pradeepsen99 committed Mar 24, 2024
1 parent f1ce3f2 commit be3fc29
Show file tree
Hide file tree
Showing 4 changed files with 335 additions and 186 deletions.
16 changes: 8 additions & 8 deletions src/reducer/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {createSlice} from '@reduxjs/toolkit'
import {initFrameData, updateFrameData, getFrameData, initAnnotationData, updateAnnotationData, getAnnotationData, initColumnData, setMedia, initMedia} from '../processing/actions'


const initialState = {horizontal_res: 0, vertical_res: 0, frame_rate: 1, media_type: "in_video", total_frames: 0, skip_value: 1}
const initialState = {horizontal_res: 0, vertical_res: 0, frame_rate: 1, media_type: "in_video", total_frames: 0, skip_value: null}

const metadataSlice = createSlice({
name: 'metadata',
Expand All @@ -20,13 +20,13 @@ const metadataSlice = createSlice({
state.vertical_res = payload.payload.vertical_res
},
setFrameRate(state, payload){
// When the frame rate is changed, we first calculate the current frame rate and then multiply the total frames by the ratio of the new frame rate to the old frame rate
if (state.media_type != "in_image") { // only for videos
var curr_framerate = JSON.parse(JSON.stringify(state))['frame_rate']
state.total_frames = state.total_frames / curr_framerate
state.total_frames = state.total_frames * payload.payload.frame_rate
state.frame_rate = payload.payload.frame_rate
}
// When the frame rate is changed, we first calculate the current frame rate and then multiply the total frames by the ratio of the new frame rate to the old frame rate
if (state.media_type != "in_image") { // only for videos
// var curr_framerate = JSON.parse(JSON.stringify(state))['frame_rate']
// state.total_frames = state.total_frames / curr_framerate
// state.total_frames = state.total_frames * payload.payload.frame_rate
state.frame_rate = payload.payload.frame_rate
}
},
setMediaType(state, payload){
state.media_type = payload.payload.media_type
Expand Down
235 changes: 63 additions & 172 deletions src/ui_elements/Components/nav_bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,226 +10,117 @@ import Form from 'react-bootstrap/Form'
import Dropdown from 'react-bootstrap/Dropdown'
import { ButtonGroup } from 'react-bootstrap';
import Modal from 'react-bootstrap/Modal'
import Col from 'react-bootstrap/Col'
import InputGroup from 'react-bootstrap/InputGroup'

import "react-datepicker/dist/react-datepicker.css";

import Instructions from './instructions';
import { downloadFileJSON} from '../../processing/download';
import { downloadFileJSON } from '../../processing/download';

import ExportingAnnotation from '../../processing/exporting_annotation';
import ProcessVideo from './process_video';
import store from '../../store'
import {INPUT_IMAGE, INPUT_VIDEO} from '../../static_data/const'
import store from '../../store'
import { INPUT_IMAGE, INPUT_VIDEO } from '../../static_data/const'
import { useSelector } from "react-redux";
import UploadModal from './upload_modal';

import {initFrameData, updateFrameData, getFrameData, initAnnotationData, updateAnnotationData, getAnnotationData, initColumnData, setMedia, initMedia, setFrameRate, setMediaType, setSkipValue, getMetaData, togglePlay} from '../../processing/actions'
import { initFrameData, updateFrameData, getFrameData, initAnnotationData, updateAnnotationData, getAnnotationData, initColumnData, setMedia, initMedia, setFrameRate, setMediaType, setSkipValue, getMetaData, togglePlay, setTotalFrames } from '../../processing/actions'
import { init } from '../../reducer/frame_data';

initMedia(1)
export default function CustomNavBar(props){
export default function CustomNavBar(props) {
const [show, setShow] = useState(false);
const [uploadShow, setUploadShow] = useState(true);
const [videoFormat, setVideoFormat] = useState(INPUT_VIDEO)
const [process, setProcess] = useState(false)
const [columnLoad, setColumnLoad] = useState(false)
const [numStrems, setNumStreams] = useState(1)
const [playText, setPlayText] = useState(false)
const [firstUpload, setFirstUpload] = useState(false)
const [stateFrameRate, setStateFrameRate] = useState(null)
const [stateSkipValue, setStateSkipValue] = useState(null)

const play_redux = useSelector(state => state.play_status.play)

const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const handleUploadClose = () => {setUploadShow(false); setProcess(true)}
const handleUploadShow = () => {
setUploadShow(true)
const handleUploadToggle = () => {
setUploadShow(!uploadShow)
}
const play_redux = useSelector(state => state.play_status.play)


const handleDownloadJSON = () => {
var converted_annot = new ExportingAnnotation(store.getState().frame_data.data, props.video_width, props.video_height, getMetaData(), store.getState().media_data.data[0]).get_frame_json()
console.log(converted_annot)
downloadFileJSON(converted_annot, getMetaData())
}
const handleVideoFormat = (type) => {
//TODO Make sure bug is resolved and simply have video format equal type
//type = parseInt(type)
if(type === INPUT_VIDEO){
setVideoFormat(INPUT_VIDEO)
setMediaType(INPUT_VIDEO)
}else if (type === INPUT_IMAGE){
setVideoFormat(INPUT_IMAGE)
setMediaType(INPUT_IMAGE)
}else {
alert("Wrong input detected - please report this bug.")
}
}

const convertFileToURLBlob = (file) => {
return URL.createObjectURL(file)
}

const handleMediaUpload = (event) => {
if(videoFormat == INPUT_VIDEO){
setMedia(parseInt(event.target.id), event.target.files)
}else{
setMedia(parseInt(event.target.id), event.target.files)
}
}

const handleColumnUpload = (event) => {
var promise = downloadColumn(event)
promise.then(function (result) {
if(result['columns'] == undefined){
alert("Error in processing columns. Please check the file and try again.")
return;
}

if(result != null){
setColumnLoad(true);
initColumnData(result)
}else{
alert("Error in processing columns. Please check the file and try again.")
return;
}
})
}

const downloadColumn = (file) => {
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onload = function(e) {
resolve((JSON.parse(e.target.result)));
}
reader.readAsText(file.target.files[0])
})
}

const handleStreamNumChange = (event) => {
setNumStreams(event.target.value)
initMedia(event.target.value)
}

const generateUploadButtons = () => {
var uploadButtons = []
for(var i = 0; i < numStrems; i++){
let button_image = (
<Form key={i} style={{float: "left",gridColumn: 1, gridRow:4}}>
<Form.File multiple id={i+""} key={i} label={"Image Upload " + i} accept="image/*" custom type="file" onChange={(event) => {handleMediaUpload(event)}} />
</Form>
)
let button_video = (
<Form key={i} style={{float: "left",gridColumn: 1, gridRow:4}}>
<Form.File id={i+""} key={i} label={"Video Upload " + i} accept=".mp4" custom type="file" onChange={(event) => {handleMediaUpload(event)}} />
</Form>
)
if (videoFormat === INPUT_IMAGE){
uploadButtons.push(button_image)
}else if (videoFormat === INPUT_VIDEO){
uploadButtons.push(button_video)
}
}
return (
<div>
{
uploadButtons.map((but, _) => {
return (
but
)
})
}
</div>
)
}

const handlePlaying = (event) => {
togglePlay()
}

useEffect(() => {
if (play_redux == false){
if (play_redux == false) {
setPlayText("Play")
}else {
} else {
setPlayText("Pause")
}
}, [play_redux])

return (
<div>
<Modal show={show} onHide={handleClose} size='lg'>
<Modal.Header closeButton>
<Modal.Title>Instructions</Modal.Title>
</Modal.Header>
<Modal.Body><Instructions></Instructions></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>Close</Button>
</Modal.Footer>
</Modal>
<Modal show={uploadShow} onHide={handleUploadClose} size='lg' backdrop='static'>
<Modal.Header>
<Modal.Title>Upload</Modal.Title>
</Modal.Header>
<Modal.Body>
<div style={{display: "grid"}}>
{/*onClick and onBlur events are for the sole purpose to stop the eventKeys from firing off*/}
<Form >
Media Format:
<Form.Control
as="select"
id="inlineFormCustomSelect"
onChange={(event)=>{handleVideoFormat(event.target.value)}}
defaultValue={videoFormat}
>
<option value={INPUT_VIDEO}>Video</option>
<option value={INPUT_IMAGE}>Image</option>
</Form.Control>
<NavDropdown.Divider />
</Form>
<div>
Stream Num: <input type="number" defaultValue={1} onClick={(event) => {props.toggleKeyCheck(false)}} onBlur={(event) => {props.toggleKeyCheck(true)}} onChange={handleStreamNumChange}></input>
</div>
<NavDropdown.Divider />
{
generateUploadButtons()
}
<NavDropdown.Divider />
<Form >
<Form.File disabled={props.disable_buttons} accept=".json" id="file" label="Column Upload" custom type="file" onChange={handleColumnUpload}/>
</Form>
<Form >
<Form.File accept=".json" id="file" label="Annotation Upload" custom type="file" onChange={props.handleOldAnnotation}/>
</Form>
<NavDropdown.Divider />
Frame Rate: <input type="number" onClick={(event) => {props.toggleKeyCheck(false)}} onBlur={(event) => {props.toggleKeyCheck(true)}} onChange={(event) => {setFrameRate(event.target.value);}}></input>
<NavDropdown.Divider />
Skip Value: <input type='number' defaultValue="1" onChange={(event) => {setSkipValue(event.target.value)}}></input>
<NavDropdown.Divider />
</div>
</Modal.Body>
<Modal.Footer>
<Button variant="success" onClick={handleUploadClose}>Upload</Button>
</Modal.Footer>
</Modal>
<Navbar sticky="top" bg="dark" variant="dark" className="bg-5">
<Modal
show={show}
onHide={handleClose}
size='lg'
backdrop='static'
>
<Modal.Header closeButton>
<Modal.Title>Instructions</Modal.Title>
</Modal.Header>
<Modal.Body><Instructions></Instructions></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>Close</Button>
</Modal.Footer>
</Modal>
<UploadModal
handleOldAnnotation={props.handleOldAnnotation}
handleUploadToggle={handleUploadToggle}
uploadShow={uploadShow}
/>
<Navbar sticky="top" bg="dark" variant="dark" className="bg-5">
<Navbar.Brand href="#home">AVAT</Navbar.Brand>
<Nav className="mr-auto">
<NavDropdown disabled={props.disable_buttons} title="Export" id="basic-nav-dropdown">
<NavDropdown.Item onClick={handleDownloadJSON}>JSON</NavDropdown.Item>
<NavDropdown.Divider />
</NavDropdown>
<NavLink onClick={handleShow}>Instructions</NavLink>
<NavLink onClick={props.handle_link_open}>Report</NavLink>
<NavDropdown disabled={props.disable_buttons} title="Export" id="basic-nav-dropdown">
<NavDropdown.Item onClick={handleDownloadJSON}>JSON</NavDropdown.Item>
<NavDropdown.Divider />
</NavDropdown>
<NavLink onClick={handleShow}>Instructions</NavLink>
<NavLink onClick={props.handle_link_open}>Report</NavLink>
</Nav>
<div>
<Button variant="outline-success" onClick={handleUploadShow}>Upload</Button>{' '}
<Button variant="outline-success" onClick={handleUploadToggle}>Settings</Button>{' '}
{' '}
<Dropdown as={ButtonGroup}>
<Button variant="secondary" disabled={true}>{props.display_frame_num}</Button>{' '}
<Dropdown.Toggle split variant="secondary" id="dropdown-split-basic" />
<Dropdown.Menu>
Skip Value: <input type='number' defaultValue="1" onChange={(event) => {setSkipValue(event.target.value)}}></input>
<Form>
<Form.Label>Skip Value</Form.Label>
<Form.Control
placeholder='Skip Value'
type='number'
onChange={(event) => { setSkipValue(event.target.value) }}
onClick={props.toggleKeyCheck(false)}
onBlur={props.toggleKeyCheck(true)}
defaultValue={props.skip_value}
/>
</Form>
</Dropdown.Menu>
</Dropdown>{' '}

<Button variant="primary" disabled={props.disable_buttons} onClick={props.skip_frame_backward}>Prev</Button>{' '}
{
videoFormat === INPUT_VIDEO &&
videoFormat === INPUT_VIDEO &&
<Button variant="primary" disabled={props.disable_buttons} onClick={handlePlaying}>{playText}</Button>
}
{' '}
Expand All @@ -238,14 +129,14 @@ export default function CustomNavBar(props){
<Button variant="success" onClick={props.addToCanvas}>Add</Button>
<Dropdown.Toggle split variant="success" id="dropdown-split-basic" />
<Dropdown.Menu>
<Dropdown.Item onClick={(event) =>{props.change_annotation_type("1")}}>Behavior Annotation</Dropdown.Item>
<Dropdown.Item onClick={(event) =>{props.change_annotation_type("2")}}>BoundingBox</Dropdown.Item>
<Dropdown.Item onClick={(event) =>{props.change_annotation_type("3")}}>Segmentation</Dropdown.Item>
<Dropdown.Item onClick={(event) => { props.change_annotation_type("1") }}>Behavior Annotation</Dropdown.Item>
<Dropdown.Item onClick={(event) => { props.change_annotation_type("2") }}>BoundingBox</Dropdown.Item>
<Dropdown.Item onClick={(event) => { props.change_annotation_type("3") }}>Segmentation</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
{/*<Button variant="danger" onClick={remove} disabled={disable_buttons} style={{position:"relative"}}>Remove</Button>{' '}*/}
</div>
</Navbar>
</Navbar>
</div>
)
}
Loading

0 comments on commit be3fc29

Please sign in to comment.