Skip to content
Snippets Groups Projects
Commit 7942ec9a authored by Anthony's avatar Anthony
Browse files

Merge branch 'feature/SliderRangeTime/AntoineTest' into 'tetras-main'

Change on the slide bar's UI from pluggin annotation

See merge request !7
parents 1dd0ef44 0cd17e32
Branches
No related tags found
1 merge request!7Change on the slide bar's UI from pluggin annotation
Pipeline #1649 failed
...@@ -5,3 +5,5 @@ ...@@ -5,3 +5,5 @@
/node_modules /node_modules
/umd /umd
npm-debug.log* npm-debug.log*
.idea
.nvmrc 0 → 100644
16.20.2
\ No newline at end of file
...@@ -17,6 +17,7 @@ Persisting annotations requires implementing an a IIIF annotation server. Severa ...@@ -17,6 +17,7 @@ Persisting annotations requires implementing an a IIIF annotation server. Severa
`mirador-annotations` requires an instance of Mirador 3. See the [Mirador wiki](https://github.com/ProjectMirador/mirador/wiki) for examples of embedding Mirador within an application. See the [live demo's index.js](https://github.com/ProjectMirador/mirador-annotations/blob/master/demo/src/index.js) for an example of importing the `mirador-annotations` plugin and configuring the adapter. `mirador-annotations` requires an instance of Mirador 3. See the [Mirador wiki](https://github.com/ProjectMirador/mirador/wiki) for examples of embedding Mirador within an application. See the [live demo's index.js](https://github.com/ProjectMirador/mirador-annotations/blob/master/demo/src/index.js) for an example of importing the `mirador-annotations` plugin and configuring the adapter.
**You must use node v16.20.2**. You can `run nvm use` at the racine of the project to set your node version to 16.20.2.
## Contribute ## Contribute
Mirador's development, design, and maintenance is driven by community needs and ongoing feedback and discussion. Join us at our regularly scheduled community calls, on [IIIF slack #mirador](http://bit.ly/iiif-slack), or the [mirador-tech](https://groups.google.com/forum/#!forum/mirador-tech) and [iiif-discuss](https://groups.google.com/forum/#!forum/iiif-discuss) mailing lists. To suggest features, report bugs, and clarify usage, please submit a GitHub issue. Mirador's development, design, and maintenance is driven by community needs and ongoing feedback and discussion. Join us at our regularly scheduled community calls, on [IIIF slack #mirador](http://bit.ly/iiif-slack), or the [mirador-tech](https://groups.google.com/forum/#!forum/mirador-tech) and [iiif-discuss](https://groups.google.com/forum/#!forum/iiif-discuss) mailing lists. To suggest features, report bugs, and clarify usage, please submit a GitHub issue.
......
This diff is collapsed.
...@@ -19,13 +19,13 @@ import StrokeColorIcon from '@material-ui/icons/BorderColor'; ...@@ -19,13 +19,13 @@ import StrokeColorIcon from '@material-ui/icons/BorderColor';
import LineWeightIcon from '@material-ui/icons/LineWeight'; import LineWeightIcon from '@material-ui/icons/LineWeight';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'; import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import FormatShapesIcon from '@material-ui/icons/FormatShapes'; import FormatShapesIcon from '@material-ui/icons/FormatShapes';
import TextField from '@material-ui/core/TextField';
import { SketchPicker } from 'react-color'; import { SketchPicker } from 'react-color';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import CompanionWindow from 'mirador/dist/es/src/containers/CompanionWindow'; import CompanionWindow from 'mirador/dist/es/src/containers/CompanionWindow';
import { VideosReferences } from 'mirador/dist/es/src/plugins/VideosReferences'; import { VideosReferences } from 'mirador/dist/es/src/plugins/VideosReferences';
import { OSDReferences } from 'mirador/dist/es/src/plugins/OSDReferences'; import { OSDReferences } from 'mirador/dist/es/src/plugins/OSDReferences';
import Slider from '@material-ui/core/Slider';
import AnnotationDrawing from './AnnotationDrawing'; import AnnotationDrawing from './AnnotationDrawing';
import TextEditor from './TextEditor'; import TextEditor from './TextEditor';
import WebAnnotation from './WebAnnotation'; import WebAnnotation from './WebAnnotation';
...@@ -33,7 +33,6 @@ import CursorIcon from './icons/Cursor'; ...@@ -33,7 +33,6 @@ import CursorIcon from './icons/Cursor';
import HMSInput from './HMSInput'; import HMSInput from './HMSInput';
import ImageFormField from './ImageFormField'; import ImageFormField from './ImageFormField';
import { secondsToHMS } from './utils'; import { secondsToHMS } from './utils';
/** Extract time information from annotation target */ /** Extract time information from annotation target */
function timeFromAnnoTarget(annotarget) { function timeFromAnnoTarget(annotarget) {
console.info('TODO proper time extraction from: ', annotarget); console.info('TODO proper time extraction from: ', annotarget);
...@@ -62,7 +61,6 @@ class AnnotationCreation extends Component { ...@@ -62,7 +61,6 @@ class AnnotationCreation extends Component {
super(props); super(props);
const annoState = {}; const annoState = {};
if (props.annotation) { if (props.annotation) {
// //
// annotation body // annotation body
...@@ -136,8 +134,12 @@ class AnnotationCreation extends Component { ...@@ -136,8 +134,12 @@ class AnnotationCreation extends Component {
svg: null, svg: null,
textBody: '', textBody: '',
textEditorStateBustingKey: 0, textEditorStateBustingKey: 0,
// eslint-disable-next-line sort-keys,max-len
// TO DO : The state must be updated with the video's timing information when the component is mounted
valueTime: [0, 1],
xywh: null, xywh: null,
...annoState, ...annoState,
valuetextTime: '',
}; };
this.submitForm = this.submitForm.bind(this); this.submitForm = this.submitForm.bind(this);
...@@ -159,6 +161,8 @@ class AnnotationCreation extends Component { ...@@ -159,6 +161,8 @@ class AnnotationCreation extends Component {
this.closeChooseColor = this.closeChooseColor.bind(this); this.closeChooseColor = this.closeChooseColor.bind(this);
this.updateStrokeColor = this.updateStrokeColor.bind(this); this.updateStrokeColor = this.updateStrokeColor.bind(this);
this.handleImgChange = this.handleImgChange.bind(this); this.handleImgChange = this.handleImgChange.bind(this);
this.handleChangeTime = this.handleChangeTime.bind(this);
this.valuetextTime = this.valuetextTime.bind(this);
} }
/** */ /** */
...@@ -196,16 +200,23 @@ class AnnotationCreation extends Component { ...@@ -196,16 +200,23 @@ class AnnotationCreation extends Component {
this.setState({ tend: Math.floor(this.props.currentTime) }); this.setState({ tend: Math.floor(this.props.currentTime) });
} }
handleChangeTime = (event, newValueTime) => {
const timeStart = newValueTime[0];
const timeEnd = newValueTime[1];
this.updateTstart(timeStart);
this.updateTend(timeEnd);
this.seekToTstart();
this.seekToTend();
this.setState({ valueTime: newValueTime });
};
/** update annotation start time */
updateTstart(value) { this.setState({ tstart: value }); }
/** update annotation end time */
updateTend(value) { this.setState({ tend: value }); }
/** seekTo/goto annotation start time */ /** seekTo/goto annotation start time */
seekToTstart() {
const { paused, setCurrentTime, setSeekTo } = this.props;
const { tstart } = this.state;
if (!paused) {
this.setState(setSeekTo(tstart));
} else {
this.setState(setCurrentTime(tstart));
}
}
/** seekTo/goto annotation end time */ /** seekTo/goto annotation end time */
seekToTend() { seekToTend() {
...@@ -218,11 +229,21 @@ class AnnotationCreation extends Component { ...@@ -218,11 +229,21 @@ class AnnotationCreation extends Component {
} }
} }
/** update annotation start time */ // eslint-disable-next-line require-jsdoc
updateTstart(value) { this.setState({ tstart: value }); } seekToTstart() {
const { paused, setCurrentTime, setSeekTo } = this.props;
const { tstart } = this.state;
if (!paused) {
this.setState(setSeekTo(tstart));
} else {
this.setState(setCurrentTime(tstart));
}
}
/** update annotation end time */ // eslint-disable-next-line require-jsdoc
updateTend(value) { this.setState({ tend: value }); } valuetextTime() {
return this.valueTime;
}
/** */ /** */
openChooseColor(e) { openChooseColor(e) {
...@@ -342,10 +363,17 @@ class AnnotationCreation extends Component { ...@@ -342,10 +363,17 @@ class AnnotationCreation extends Component {
activeTool, colorPopoverOpen, currentColorType, fillColor, popoverAnchorEl, activeTool, colorPopoverOpen, currentColorType, fillColor, popoverAnchorEl,
strokeColor, popoverLineWeightAnchorEl, lineWeightPopoverOpen, strokeWidth, closedMode, strokeColor, popoverLineWeightAnchorEl, lineWeightPopoverOpen, strokeWidth, closedMode,
textBody, svg, tstart, tend, textBody, svg, tstart, tend,
textEditorStateBustingKey, image, textEditorStateBustingKey, image, valueTime,
} = this.state; } = this.state;
let mediaVideo;
// TODO : Vérifier ce code, c'est étrange de comprarer un typeof à une chaine de caractère.
const mediaIsVideo = typeof VideosReferences.get(windowId) !== 'undefined'; const mediaIsVideo = typeof VideosReferences.get(windowId) !== 'undefined';
if (mediaIsVideo) {
mediaVideo = VideosReferences.get(windowId);
valueTime[0] = tstart;
valueTime[1] = tend;
}
return ( return (
<CompanionWindow <CompanionWindow
...@@ -366,6 +394,97 @@ class AnnotationCreation extends Component { ...@@ -366,6 +394,97 @@ class AnnotationCreation extends Component {
player={mediaIsVideo ? VideosReferences.get(windowId) : OSDReferences.get(windowId)} player={mediaIsVideo ? VideosReferences.get(windowId) : OSDReferences.get(windowId)}
/> />
<form onSubmit={this.submitForm} className={classes.section}> <form onSubmit={this.submitForm} className={classes.section}>
<div>
<Grid item xs={12}>
<Typography variant="overline">
Text Content
</Typography>
</Grid>
<Grid item xs={12}>
<TextEditor
key={textEditorStateBustingKey}
annoHtml={textBody}
updateAnnotationBody={this.updateTextBody}
/>
</Grid>
</div>
<div>
{ mediaIsVideo && (
<>
<Grid item xs={12} className={classes.paper}>
<Typography id="range-slider" variant="overline">
Display period
</Typography>
{/* <Typography>
{mediaIsVideo ? mediaVideo?.video.duration : null}
</Typography> */}
<Slider
value={valueTime}
onChange={this.handleChangeTime}
valueLabelDisplay="auto"
aria-labelledby="range-slider"
getAriaValueText={secondsToHMS}
max={mediaVideo ? mediaVideo.video.duration : null}
color="secondary"
classes={{
root: classes.MuiSliderColorSecondary,
}}
/>
</Grid>
<div className={`${classes.paper} ${classes.selectTimeField} `}>
<div className={`${classes.paper} ${classes.selectTimeModule} `}>
<div className={classes.buttonTimeContainer}>
<div>
<p className={classes.textTimeButton}>Start</p>
</div>
<ToggleButton
value="true"
title="Set current time"
size="small"
onClick={this.setTstartNow}
className={classes.timecontrolsbutton}
>
<Alarm fontSize="small" />
</ToggleButton>
</div>
<HMSInput seconds={tstart} onChange={this.updateTstart} />
</div>
<div className={`${classes.paper} ${classes.selectTimeModule}`}>
<div className={classes.buttonTimeContainer}>
<div>
<p className={classes.textTimeButton}>End</p>
</div>
<ToggleButton
value="true"
title="Set current time"
size="small"
onClick={this.setTendNow}
className={classes.timecontrolsbutton}
>
<Alarm fontSize="small" />
</ToggleButton>
</div>
<HMSInput seconds={tend} onChange={this.updateTend} />
</div>
</div>
</>
)}
</div>
<div>
<Grid container>
<Grid item xs={12}>
<Typography variant="overline">
Image Content
</Typography>
</Grid>
<Grid item xs={12} style={{ marginBottom: 10 }}>
<ImageFormField value={image} onChange={this.handleImgChange} />
</Grid>
</Grid>
</div>
<div>
<Grid container> <Grid container>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="overline"> <Typography variant="overline">
...@@ -414,6 +533,8 @@ class AnnotationCreation extends Component { ...@@ -414,6 +533,8 @@ class AnnotationCreation extends Component {
</Paper> </Paper>
</Grid> </Grid>
</Grid> </Grid>
</div>
<div>
<Grid container> <Grid container>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="overline"> <Typography variant="overline">
...@@ -472,69 +593,15 @@ class AnnotationCreation extends Component { ...@@ -472,69 +593,15 @@ class AnnotationCreation extends Component {
} }
</Grid> </Grid>
</Grid> </Grid>
<Grid container> </div>
{ mediaIsVideo && ( <div>
<>
<Grid item xs={12}>
<ToggleButton value="true" title="Go to start time" size="small" onClick={this.seekToTstart} className={classes.timecontrolsbutton}>
<LastPage />
</ToggleButton>
<Typography variant="overline">
Start
</Typography>
</Grid>
<Grid item xs={12} className={classes.paper}>
<ToggleButton value="true" title="Set current time" size="small" onClick={this.setTstartNow} className={classes.timecontrolsbutton}>
<Alarm />
</ToggleButton>
<HMSInput seconds={tstart} onChange={this.updateTstart} />
</Grid>
<Grid item xs={12}>
<Typography variant="overline">
<ToggleButton value="true" title="Go to end time" size="small" onClick={this.seekToTend} className={classes.timecontrolsbutton}>
<LastPage />
</ToggleButton>
End
</Typography>
</Grid>
<Grid item xs={12} className={classes.paper}>
<ToggleButton value="true" title="Set current time" size="small" onClick={this.setTendNow} className={classes.timecontrolsbutton}>
<Alarm />
</ToggleButton>
<HMSInput seconds={tend} onChange={this.updateTend} />
</Grid>
</>
)}
<Grid item xs={12}>
<Typography variant="overline">
Image Content
</Typography>
</Grid>
<Grid item xs={12} style={{ marginBottom: 10 }}>
<ImageFormField value={image} onChange={this.handleImgChange} />
</Grid>
<Grid item xs={12}>
<Typography variant="overline">
Text Content
</Typography>
</Grid>
<Grid item xs={12}>
<TextEditor
key={textEditorStateBustingKey}
annoHtml={textBody}
updateAnnotationBody={this.updateTextBody}
/>
</Grid>
</Grid>
<Button onClick={closeCompanionWindow}> <Button onClick={closeCompanionWindow}>
Cancel Cancel
</Button> </Button>
<Button variant="contained" color="primary" type="submit"> <Button variant="contained" color="primary" type="submit">
Save Save
</Button> </Button>
</div>
</form> </form>
<Popover <Popover
open={lineWeightPopoverOpen} open={lineWeightPopoverOpen}
...@@ -574,9 +641,12 @@ class AnnotationCreation extends Component { ...@@ -574,9 +641,12 @@ class AnnotationCreation extends Component {
); );
} }
} }
/** */ /** */
const styles = (theme) => ({ const styles = (theme) => ({
buttonTimeContainer: {
display: 'flex',
flexDirection: 'column',
},
divider: { divider: {
margin: theme.spacing(1, 0.5), margin: theme.spacing(1, 0.5),
}, },
...@@ -590,22 +660,48 @@ const styles = (theme) => ({ ...@@ -590,22 +660,48 @@ const styles = (theme) => ({
border: 'none', border: 'none',
margin: theme.spacing(0.5), margin: theme.spacing(0.5),
}, },
MuiSliderColorSecondary: {
color: 'rgba(1, 0, 0, 0.38)',
},
paper: { paper: {
display: 'flex', display: 'flex',
flexWrap: 'wrap', flexWrap: 'wrap',
}, },
section: { section: {
display: 'flex',
flexDirection: 'column',
gap: '20px',
paddingBottom: theme.spacing(1), paddingBottom: theme.spacing(1),
paddingLeft: theme.spacing(2), paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1), paddingRight: theme.spacing(1),
paddingTop: theme.spacing(2), paddingTop: theme.spacing(2),
}, },
selectTimeField: {
alignContent: 'center',
display: 'flex',
flexDirection: 'wrap',
gap: '5px',
padding: '5px',
},
selectTimeModule: {
border: '1px solid rgba(0, 0, 0, 0.12)',
borderRadius: '4px',
display: 'flex',
flexWrap: 'nowrap',
justifyContent: 'center',
padding: '5px',
},
textTimeButton: {
fontSize: '15px',
margin: 0,
minWidth: '40px',
},
timecontrolsbutton: { timecontrolsbutton: {
border: 'none',
height: '30px', height: '30px',
margin: 'auto', margin: 'auto',
marginLeft: '0', marginLeft: '0',
marginRight: '5px', marginRight: '5px',
width: '30px',
}, },
}); });
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import { IconButton, Input } from '@material-ui/core'; import { IconButton, Input, TextField } from '@material-ui/core';
import { ArrowDownward, ArrowUpward } from '@material-ui/icons'; import { ArrowDownward, ArrowUpward } from '@material-ui/icons';
import { secondsToHMSarray } from './utils'; import { secondsToHMSarray } from './utils';
...@@ -18,10 +18,7 @@ class HMSInput extends Component { ...@@ -18,10 +18,7 @@ class HMSInput extends Component {
minutes: m, minutes: m,
seconds: s, seconds: s,
}; };
this.someChange = this.someChange.bind(this); this.someChange = this.someChange.bind(this);
this.addOneSec = this.addOneSec.bind(this);
this.subOneSec = this.subOneSec.bind(this);
} }
/** update */ /** update */
...@@ -44,18 +41,6 @@ class HMSInput extends Component { ...@@ -44,18 +41,6 @@ class HMSInput extends Component {
onChange(state.hours * 3600 + state.minutes * 60 + state.seconds); onChange(state.hours * 3600 + state.minutes * 60 + state.seconds);
} }
/** Add one second by simulating an input change */
addOneSec() {
const { seconds } = this.state;
this.someChange({ target: { name: 'seconds', value: seconds + 1 } });
}
/** Substract one second by simulating an input change */
subOneSec() {
const { seconds } = this.state;
this.someChange({ target: { name: 'seconds', value: seconds - 1 } });
}
/** Render */ /** Render */
render() { render() {
const { hours, minutes, seconds } = this.state; const { hours, minutes, seconds } = this.state;
...@@ -63,17 +48,22 @@ class HMSInput extends Component { ...@@ -63,17 +48,22 @@ class HMSInput extends Component {
return ( return (
<div className={classes.root}> <div className={classes.root}>
<div className={classes.root}> <div className={classes.root}>
<Input className={classes.input} name="hours" value={hours} onChange={this.someChange} /> <Input
<Input className={classes.input} name="minutes" value={minutes} onChange={this.someChange} /> className={classes.input}
<Input className={classes.input} name="seconds" value={seconds} onChange={this.someChange} /> variant="filled"
</div> type="number"
<div className={classes.flexcol}> min="0"
<IconButton size="small" onClick={this.addOneSec}> pattern
<ArrowUpward /> name="hours"
</IconButton> value={hours}
<IconButton size="small" onClick={this.subOneSec}> onChange={this.someChange}
<ArrowDownward /> inputProps={{ style: { textAlign: 'center' } }}
</IconButton> />
<span className={classes.hmsLabel}>h</span>
<Input className={classes.input} type="number" min="0" max="59" name="minutes" value={minutes} onChange={this.someChange} inputProps={{ style: { textAlign: 'center' } }} />
<span className={classes.hmsLabel}>m</span>
<Input className={classes.input} type="number" min="0" max="59" name="seconds" value={seconds} onChange={this.someChange} inputProps={{ style: { textAlign: 'center' } }} />
<span className={classes.hmsLabel}>s</span>
</div> </div>
</div> </div>
); );
...@@ -85,7 +75,6 @@ const styles = (theme) => ({ ...@@ -85,7 +75,6 @@ const styles = (theme) => ({
root: { root: {
alignItems: 'center', alignItems: 'center',
display: 'flex', display: 'flex',
justifyContent: 'end',
}, },
// eslint-disable-next-line sort-keys // eslint-disable-next-line sort-keys
flexcol: { flexcol: {
...@@ -93,12 +82,26 @@ const styles = (theme) => ({ ...@@ -93,12 +82,26 @@ const styles = (theme) => ({
flexDirection: 'column', flexDirection: 'column',
justifyContent: 'center', justifyContent: 'center',
}, },
hmsLabel: {
color: 'grey',
},
// eslint-disable-next-line sort-keys // eslint-disable-next-line sort-keys
input: { input: {
height: 'fit-content', height: 'fit-content',
margin: '2px', margin: '2px',
textAlign: 'center', // remove arrow from field for Firefox
width: '4ch', '& 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,
},
}, },
}); });
......
...@@ -71,6 +71,14 @@ class TextEditor extends Component { ...@@ -71,6 +71,14 @@ class TextEditor extends Component {
return ( return (
<div> <div>
<div className={classes.editorRoot} onClick={this.handleFocus}>
<Editor
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
ref={this.editorRef}
/>
</div>
<ToggleButtonGroup <ToggleButtonGroup
size="small" size="small"
value={currentStyle.toArray()} value={currentStyle.toArray()}
...@@ -88,15 +96,6 @@ class TextEditor extends Component { ...@@ -88,15 +96,6 @@ class TextEditor extends Component {
<ItalicIcon/> <ItalicIcon/>
</ToggleButton> </ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
<div className={classes.editorRoot} onClick={this.handleFocus}>
<Editor
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
ref={this.editorRef}
/>
</div>
</div> </div>
); );
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment