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

Merge branch 'tetras-main' into 'fix-deployment'

# Conflicts:
#   package.json
parents 5d14cc1f 7942ec9a
No related branches found
No related tags found
1 merge request!8create nvmrc and add babel plugin in dev dependencies
Pipeline #1650 failed
......@@ -5,3 +5,5 @@
/node_modules
/umd
npm-debug.log*
.idea
......@@ -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.
**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
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.
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -19,13 +19,13 @@ import StrokeColorIcon from '@material-ui/icons/BorderColor';
import LineWeightIcon from '@material-ui/icons/LineWeight';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import FormatShapesIcon from '@material-ui/icons/FormatShapes';
import TextField from '@material-ui/core/TextField';
import { SketchPicker } from 'react-color';
import { v4 as uuid } from 'uuid';
import { withStyles } from '@material-ui/core/styles';
import CompanionWindow from 'mirador/dist/es/src/containers/CompanionWindow';
import { VideosReferences } from 'mirador/dist/es/src/plugins/VideosReferences';
import { OSDReferences } from 'mirador/dist/es/src/plugins/OSDReferences';
import Slider from '@material-ui/core/Slider';
import AnnotationDrawing from './AnnotationDrawing';
import TextEditor from './TextEditor';
import WebAnnotation from './WebAnnotation';
......@@ -33,7 +33,6 @@ import CursorIcon from './icons/Cursor';
import HMSInput from './HMSInput';
import ImageFormField from './ImageFormField';
import { secondsToHMS } from './utils';
/** Extract time information from annotation target */
function timeFromAnnoTarget(annotarget) {
console.info('TODO proper time extraction from: ', annotarget);
......@@ -62,7 +61,6 @@ class AnnotationCreation extends Component {
super(props);
const annoState = {};
if (props.annotation) {
//
// annotation body
......@@ -136,8 +134,12 @@ class AnnotationCreation extends Component {
svg: null,
textBody: '',
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,
...annoState,
valuetextTime: '',
};
this.submitForm = this.submitForm.bind(this);
......@@ -159,6 +161,8 @@ class AnnotationCreation extends Component {
this.closeChooseColor = this.closeChooseColor.bind(this);
this.updateStrokeColor = this.updateStrokeColor.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 {
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 */
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 */
seekToTend() {
......@@ -218,11 +229,21 @@ class AnnotationCreation extends Component {
}
}
/** update annotation start time */
updateTstart(value) { this.setState({ tstart: value }); }
// eslint-disable-next-line require-jsdoc
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 */
updateTend(value) { this.setState({ tend: value }); }
// eslint-disable-next-line require-jsdoc
valuetextTime() {
return this.valueTime;
}
/** */
openChooseColor(e) {
......@@ -342,10 +363,17 @@ class AnnotationCreation extends Component {
activeTool, colorPopoverOpen, currentColorType, fillColor, popoverAnchorEl,
strokeColor, popoverLineWeightAnchorEl, lineWeightPopoverOpen, strokeWidth, closedMode,
textBody, svg, tstart, tend,
textEditorStateBustingKey, image,
textEditorStateBustingKey, image, valueTime,
} = 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';
if (mediaIsVideo) {
mediaVideo = VideosReferences.get(windowId);
valueTime[0] = tstart;
valueTime[1] = tend;
}
return (
<CompanionWindow
......@@ -366,6 +394,97 @@ class AnnotationCreation extends Component {
player={mediaIsVideo ? VideosReferences.get(windowId) : OSDReferences.get(windowId)}
/>
<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 item xs={12}>
<Typography variant="overline">
......@@ -414,6 +533,8 @@ class AnnotationCreation extends Component {
</Paper>
</Grid>
</Grid>
</div>
<div>
<Grid container>
<Grid item xs={12}>
<Typography variant="overline">
......@@ -472,69 +593,15 @@ class AnnotationCreation extends Component {
}
</Grid>
</Grid>
<Grid container>
{ mediaIsVideo && (
<>
<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>
</div>
<div>
<Button onClick={closeCompanionWindow}>
Cancel
</Button>
<Button variant="contained" color="primary" type="submit">
Save
</Button>
</div>
</form>
<Popover
open={lineWeightPopoverOpen}
......@@ -574,9 +641,12 @@ class AnnotationCreation extends Component {
);
}
}
/** */
const styles = (theme) => ({
buttonTimeContainer: {
display: 'flex',
flexDirection: 'column',
},
divider: {
margin: theme.spacing(1, 0.5),
},
......@@ -590,22 +660,48 @@ const styles = (theme) => ({
border: 'none',
margin: theme.spacing(0.5),
},
MuiSliderColorSecondary: {
color: 'rgba(1, 0, 0, 0.38)',
},
paper: {
display: 'flex',
flexWrap: 'wrap',
},
section: {
display: 'flex',
flexDirection: 'column',
gap: '20px',
paddingBottom: theme.spacing(1),
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1),
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: {
border: 'none',
height: '30px',
margin: 'auto',
marginLeft: '0',
marginRight: '5px',
width: '30px',
},
});
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
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 { secondsToHMSarray } from './utils';
......@@ -18,10 +18,7 @@ class HMSInput extends Component {
minutes: m,
seconds: s,
};
this.someChange = this.someChange.bind(this);
this.addOneSec = this.addOneSec.bind(this);
this.subOneSec = this.subOneSec.bind(this);
}
/** update */
......@@ -44,18 +41,6 @@ class HMSInput extends Component {
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() {
const { hours, minutes, seconds } = this.state;
......@@ -63,17 +48,22 @@ class HMSInput extends Component {
return (
<div className={classes.root}>
<div className={classes.root}>
<Input className={classes.input} name="hours" value={hours} onChange={this.someChange} />
<Input className={classes.input} name="minutes" value={minutes} onChange={this.someChange} />
<Input className={classes.input} name="seconds" value={seconds} onChange={this.someChange} />
</div>
<div className={classes.flexcol}>
<IconButton size="small" onClick={this.addOneSec}>
<ArrowUpward />
</IconButton>
<IconButton size="small" onClick={this.subOneSec}>
<ArrowDownward />
</IconButton>
<Input
className={classes.input}
variant="filled"
type="number"
min="0"
pattern
name="hours"
value={hours}
onChange={this.someChange}
inputProps={{ style: { textAlign: 'center' } }}
/>
<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>
);
......@@ -85,7 +75,6 @@ const styles = (theme) => ({
root: {
alignItems: 'center',
display: 'flex',
justifyContent: 'end',
},
// eslint-disable-next-line sort-keys
flexcol: {
......@@ -93,12 +82,26 @@ const styles = (theme) => ({
flexDirection: 'column',
justifyContent: 'center',
},
hmsLabel: {
color: 'grey',
},
// eslint-disable-next-line sort-keys
input: {
height: 'fit-content',
margin: '2px',
textAlign: 'center',
width: '4ch',
// 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,
},
},
});
......
......@@ -71,6 +71,14 @@ class TextEditor extends Component {
return (
<div>
<div className={classes.editorRoot} onClick={this.handleFocus}>
<Editor
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
ref={this.editorRef}
/>
</div>
<ToggleButtonGroup
size="small"
value={currentStyle.toArray()}
......@@ -88,15 +96,6 @@ class TextEditor extends Component {
<ItalicIcon/>
</ToggleButton>
</ToggleButtonGroup>
<div className={classes.editorRoot} onClick={this.handleFocus}>
<Editor
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
ref={this.editorRef}
/>
</div>
</div>
);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment