Skip to content
Snippets Groups Projects
Commit 65f55902 authored by Anthony's avatar Anthony
Browse files

MigratingAnnotationCreation to MUI5.

It's possible to display the creation annotation window, not validate the creation.
parent 8cedeb3c
No related branches found
No related tags found
1 merge request!10Draft: MigratingAnnotationCreation to MUI5.
Pipeline #1659 failed
...@@ -538,7 +538,7 @@ class AnnotationCreation extends Component { ...@@ -538,7 +538,7 @@ class AnnotationCreation extends Component {
<Alarm fontSize="small" /> <Alarm fontSize="small" />
</ToggleButton> </ToggleButton>
</div> </div>
{/* <HMSInput seconds={tstart} onChange={this.updateTstart} /> */} <HMSInput seconds={tstart} onChange={this.updateTstart} />
</div> </div>
<div style={{ <div style={{
border: '1px solid rgba(0, 0, 0, 0.12)', border: '1px solid rgba(0, 0, 0, 0.12)',
...@@ -580,7 +580,7 @@ class AnnotationCreation extends Component { ...@@ -580,7 +580,7 @@ class AnnotationCreation extends Component {
<Alarm fontSize="small" /> <Alarm fontSize="small" />
</ToggleButton> </ToggleButton>
</div> </div>
{/* <HMSInput seconds={tend} onChange={this.updateTend} /> */} <HMSInput seconds={tend} onChange={this.updateTend} />
</div> </div>
</div> </div>
</> </>
...@@ -594,7 +594,7 @@ class AnnotationCreation extends Component { ...@@ -594,7 +594,7 @@ class AnnotationCreation extends Component {
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} style={{ marginBottom: 10 }}> <Grid item xs={12} style={{ marginBottom: 10 }}>
{/* <ImageFormField value={image} onChange={this.handleImgChange} /> */} <ImageFormField value={image} onChange={this.handleImgChange} />
</Grid> </Grid>
</Grid> </Grid>
</div> </div>
......
import React, { Component } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { withStyles } from '@mui/material/styles'; import { Input, styled } from '@mui/material';
import { Input } from '@mui/material';
import { secondsToHMSarray } from './utils'; import { secondsToHMSarray } from './utils';
/** hh:mm:ss input which behave like a single input for parent */ const StyledInput = styled(Input)(({ theme }) => ({
class HMSInput extends Component { height: 'fit-content',
/** Initialize state structure & bindings */ margin: '2px',
constructor(props) { '& input[type=number]': {
super(props); '-moz-appearance': 'textfield',
},
'& input[type=number]::-webkit-outer-spin-button, & input[type=number]::-webkit-inner-spin-button': {
'-webkit-appearance': 'none',
margin: 0,
},
}));
// eslint-disable-next-line react/destructuring-assignment const StyledHMSLabel = styled('span')({
const [h, m, s] = secondsToHMSarray(this.props.seconds); color: 'grey',
this.state = { });
hours: h,
minutes: m,
seconds: s,
};
this.someChange = this.someChange.bind(this);
}
/** update */ const StyledRoot = styled('div')({
componentDidUpdate(prevProps) { alignItems: 'center',
const { seconds } = this.props; display: 'flex',
if (prevProps.seconds === seconds) return;
const [h, m, s] = secondsToHMSarray(seconds);
this.setState({
hours: h,
minutes: m,
seconds: s,
}); });
}
/** If one value is updated, tell the parent component the total seconds counts */ function HMSInput({ seconds, onChange }) {
someChange(ev) { const [hms, setHms] = useState(secondsToHMSarray(seconds));
const { onChange } = this.props;
const { state } = this; useEffect(() => {
state[ev.target.name] = Number(ev.target.value); setHms(secondsToHMSarray(seconds));
onChange(state.hours * 3600 + state.minutes * 60 + state.seconds); }, [seconds]);
}
const someChange = (ev) => {
const newState = { ...hms, [ev.target.name]: Number(ev.target.value) };
setHms(newState);
onChange(newState.hours * 3600 + newState.minutes * 60 + newState.seconds);
};
/** Render */
render() {
const { hours, minutes, seconds } = this.state;
const { classes } = this.props;
return ( return (
<div className={classes.root}> <StyledRoot>
<div className={classes.root}> <StyledInput
<Input
className={classes.input}
variant="filled" variant="filled"
type="number" type="number"
min="0" min="0"
pattern
name="hours" name="hours"
value={hours} value={hms.hours}
onChange={this.someChange} onChange={someChange}
inputProps={{ style: { textAlign: 'center' } }} inputProps={{ style: { textAlign: 'center' } }}
/> />
<span className={classes.hmsLabel}>h</span> <StyledHMSLabel>h</StyledHMSLabel>
<Input className={classes.input} type="number" min="0" max="59" name="minutes" value={minutes} onChange={this.someChange} inputProps={{ style: { textAlign: 'center' } }} /> <StyledInput
<span className={classes.hmsLabel}>m</span> type="number"
<Input className={classes.input} type="number" min="0" max="59" name="seconds" value={seconds} onChange={this.someChange} inputProps={{ style: { textAlign: 'center' } }} /> min="0"
<span className={classes.hmsLabel}>s</span> max="59"
</div> name="minutes"
</div> value={hms.minutes}
onChange={someChange}
inputProps={{ style: { textAlign: 'center' } }}
/>
<StyledHMSLabel>m</StyledHMSLabel>
<StyledInput
type="number"
min="0"
max="59"
name="seconds"
value={hms.seconds}
onChange={someChange}
inputProps={{ style: { textAlign: 'center' } }}
/>
<StyledHMSLabel>s</StyledHMSLabel>
</StyledRoot>
); );
} }
}
/** */
const styles = (theme) => ({
root: {
alignItems: 'center',
display: 'flex',
},
// eslint-disable-next-line sort-keys
flexcol: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
},
hmsLabel: {
color: 'grey',
},
// eslint-disable-next-line sort-keys
input: {
height: 'fit-content',
margin: '2px',
// remove arrow from field for Firefox
'& input[type=number]': {
'-moz-appearance': 'textfield',
},
// remove arrow from field for Chrome, Safari and Opera
'& input[type=number]::-webkit-outer-spin-button': {
'-webkit-appearance': 'none',
margin: 0,
},
'& input[type=number]::-webkit-inner-spin-button': {
'-webkit-appearance': 'none',
margin: 0,
},
},
});
HMSInput.propTypes = { HMSInput.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
classes: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
seconds: PropTypes.number.isRequired, seconds: PropTypes.number.isRequired,
}; };
HMSInput.defaultProps = {
};
export default HMSInput; export default HMSInput;
import React, { Component } from 'react'; import React, { useRef, useState, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { withStyles } from '@mui/material/styles'; import { TextField, styled } from '@mui/material';
import { TextField } from '@mui/material';
/** URL input with an <img> preview */ const StyledRoot = styled('div')(({ theme }) => ({
class ImageFormField extends Component { alignItems: 'center',
/** */ display: 'flex',
constructor(props) { flexDirection: 'column',
super(props); justifyContent: 'center',
}));
this.inputRef = React.createRef(); function ImageFormField({ value: image, onChange }) {
const inputRef = useRef(null);
const [imgIsValid, setImgIsValid] = useState(false);
useEffect(() => {
if (inputRef.current) {
setImgIsValid(image.id && inputRef.current.checkValidity());
} else {
setImgIsValid(!!image.id);
} }
}, [image]);
/** Render input field and a preview if the input is valid */
render() {
const { value: image, classes, onChange } = this.props;
const imgIsValid = this.inputRef.current
? (image.id && this.inputRef.current.checkValidity()) : image.id;
const imgUrl = image.id === null ? '' : image.id; const imgUrl = image.id === null ? '' : image.id;
return ( return (
<div className={classes.root}> <StyledRoot>
<TextField <TextField
value={imgUrl} value={imgUrl}
onChange={(ev) => onChange(ev.target.value)} onChange={(ev) => onChange(ev.target.value)}
...@@ -28,35 +33,18 @@ class ImageFormField extends Component { ...@@ -28,35 +33,18 @@ class ImageFormField extends Component {
label="Image URL" label="Image URL"
type="url" type="url"
fullWidth fullWidth
inputRef={this.inputRef} inputRef={inputRef}
/> />
{ imgIsValid {imgIsValid && <img src={image.id} width="100%" height="auto" alt="loading failed" />}
&& <img src={image.id} width="100%" height="auto" alt="loading failed" /> } </StyledRoot>
</div>
); );
} }
}
/** custom css */
const styles = (theme) => ({
root: {
alignItems: 'center',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
},
});
ImageFormField.propTypes = { ImageFormField.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
classes: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
value: PropTypes.shape({ value: PropTypes.shape({
id: PropTypes.string, id: PropTypes.string,
}).isRequired, }).isRequired,
}; };
ImageFormField.defaultProps = {
};
export default ImageFormField; export default ImageFormField;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment