diff --git a/src/AnnotationCreation.js b/src/AnnotationCreation.js index 7ed93cf21cd693078d5fbd63ab1ff40b6afe0263..984f097c87725e259de23ed0d39e1134981c5d92 100644 --- a/src/AnnotationCreation.js +++ b/src/AnnotationCreation.js @@ -28,7 +28,19 @@ const MANIFEST_LINK_VIEW = 'link'; /** Component for creating annotations. * Display in companion window when a manifest is open and an annoation created or edited */ -function AnnotationCreation(props) { +function AnnotationCreation({ + annotation, + canvases, + closeCompanionWindow, + config, + currentTime, + id, + mediaVideo, + receiveAnnotation, + setCurrentTime, + setSeekTo, + windowId, +}) { const [toolState, setToolState] = useState(defaultToolState); const [drawingState, setDrawingState] = useState({ @@ -42,12 +54,12 @@ function AnnotationCreation(props) { let tstart; let tend; const annoState = {}; - if (props.annotation) { - console.log('props.annotation', props.annotation); + if (annotation) { + console.log('annotation', annotation); // annotation body - if (Array.isArray(props.annotation.body)) { + if (Array.isArray(annotation.body)) { annoState.tags = []; - props.annotation.body.forEach((body) => { + annotation.body.forEach((body) => { if (body.purpose === 'tagging' && body.type === 'TextualBody') { annoState.tags.push(body.value); } else if (body.type === 'TextualBody') { @@ -59,17 +71,16 @@ function AnnotationCreation(props) { annoState.title = body; } }); - } else if (props.annotation.body.type === 'TextualBody') { - annoState.textBody = props.annotation.body.value; - } else if (props.annotation.body.type === 'Image') { - annoState.textBody = props.annotation.body.value; // why text body here ??? - annoState.image = props.annotation.body; + } else if (annotation.body.type === 'TextualBody') { + annoState.textBody = annotation.body.value; + } else if (annotation.body.type === 'Image') { + annoState.textBody = annotation.body.value; // why text body here ??? + annoState.image = annotation.body; } - // // drawing position - if (props.annotation.target.selector) { - if (Array.isArray(props.annotation.target.selector)) { - props.annotation.target.selector.forEach((selector) => { + if (annotation.target.selector) { + if (Array.isArray(annotation.target.selector)) { + annotation.target.selector.forEach((selector) => { if (selector.type === 'SvgSelector') { annoState.svg = selector.value; } else if (selector.type === 'FragmentSelector') { @@ -79,55 +90,46 @@ function AnnotationCreation(props) { } }); } else { - annoState.svg = props.annotation.target.selector.value; + annoState.svg = annotation.target.selector.value; // TODO does this happen ? when ? where are fragments selectors ? } - } else if (typeof props.annotation.target === 'string') { - annoState.xywh = geomFromAnnoTarget(props.annotation.target); - [tstart, tend] = timeFromAnnoTarget(props.annotation.target); + } else if (typeof annotation.target === 'string') { + annoState.xywh = geomFromAnnoTarget(annotation.target); + [tstart, tend] = timeFromAnnoTarget(annotation.target); + annoState.tstart = tstart; + annoState.tend = tend; } - if (props.annotation.drawingState) { - setDrawingState(JSON.parse(props.annotation.drawingState)); + if (annotation.drawingState) { + setDrawingState(JSON.parse(annotation.drawingState)); } - if (props.annotation.manifestNetwork) { - annoState.manifestNetwork = props.annotation.manifestNetwork; + if (annotation.manifestNetwork) { + annoState.manifestNetwork = annotation.manifestNetwork; + } + } else { + const video = true; + if (video) { + // Time target + annoState.tstart = currentTime ? Math.floor(currentTime) : 0; + annoState.tend = mediaVideo ? mediaVideo.props.canvas.__jsonld.duration : 0; + + // Geometry target + const targetHeigth = mediaVideo ? mediaVideo.props.canvas.__jsonld.height : 1000; + const targetWidth = mediaVideo ? mediaVideo.props.canvas.__jsonld.width : 500; + annoState.xywh = `0,0,${targetWidth},${targetHeigth}`; + } else { + // TODO image and audio case } - } - // TODO add a case where no annotation - - // TODO improve this code - if (!annoState?.xywh) { - const targetHeigth = props.mediaVideo ? props.mediaVideo.props.canvas.__jsonld.height : 1000; - const targetWidth = props.mediaVideo ? props.mediaVideo.props.canvas.__jsonld.width : 500; - annoState.xywh = `0,0,${targetWidth},${targetHeigth}`; - } - - if (!annoState?.textBody) { annoState.textBody = ''; - } - - if (!annoState?.manifestNetwork) { annoState.manifestNetwork = ''; } - // If we don't have tstart setted, we are creating a new annotation. - // If we don't have tend setted, we set it at the end of the video. - // So Tstart is current time and Tend the end of the video - if (!tstart) { - tstart = props.currentTime ? Math.floor(props.currentTime) : 0; - tend = props.mediaVideo ? props.mediaVideo.props.canvas.__jsonld.duration : 0; - } - return { ...toolState, - mediaVideo: props.mediaVideo, + mediaVideo, ...annoState, - tend, textEditorStateBustingKey: 0, - tstart, valueTime: [0, 1], - valuetextTime: '', }; }); @@ -135,7 +137,19 @@ function AnnotationCreation(props) { const [scale, setScale] = useState(1); const [viewTool, setViewTool] = useState(TARGET_VIEW); - const { height, width } = props.mediaVideo ? props.mediaVideo : 0; + + const getHeightAndWidth = () => { + if (mediaVideo) { + return mediaVideo; + } + // Todo get size from manifest image + return { + height: 1000, + width: 500, + }; + }; + + const { height, width } = getHeightAndWidth(); // TODO Check the effect to keep and remove the other // Add a state to trigger redraw @@ -167,78 +181,9 @@ function AnnotationCreation(props) { useLayoutEffect(() => { }, [{ height, width }]); - /** set annotation start time to current time */ - const setTstartNow = () => { - setState((prevState) => ({ - ...prevState, - tstart: Math.floor(props.currentTime), - })); - }; - - /** set annotation end time to current time */ - const setTendNow = () => { - setState((prevState) => ({ - ...prevState, - tend: Math.floor(props.currentTime), - })); - }; - - /** - * @param {number} newValueTime - */ - const setValueTime = (newValueTime) => { - setState((prevState) => ({ - ...prevState, - valueTime: newValueTime, - })); - }; const tabHandler = (event, TabIndex) => { setViewTool(TabIndex); }; - /** - * Change from slider - * @param {Event} event - * @param {number} newValueTime - */ - const handleChangeTime = (event, newValueTime) => { - const timeStart = newValueTime[0]; - const timeEnd = newValueTime[1]; - updateTstart(timeStart); - updateTend(timeEnd); - seekToTstart(); - setValueTime(newValueTime); - }; - - /** Change from Tstart HMS Input */ - const updateTstart = (value) => { - if (value > state.tend) { - return; - } - setState((prevState) => ({ - ...prevState, - tstart: value, - ...props.setSeekTo(value), - ...props.setCurrentTime(value), - - })); - }; - - /** update annotation end time */ - const updateTend = (value) => { - setState((prevState) => ({ - ...prevState, - tend: value, - })); - }; - - // eslint-disable-next-line require-jsdoc - const seekToTstart = () => { - setState((prevState) => ({ - ...prevState, - ...props.setSeekTo(prevState.tstart), - ...props.setCurrentTime(prevState.tstart), - })); - }; /** */ const updateGeometry = ({ svg, xywh }) => { @@ -307,7 +252,7 @@ function AnnotationCreation(props) { const closeFormCompanionWindow = () => { closeCompanionWindow('annotationCreation', { - id: props.id, + id, position: 'right', }); }; @@ -325,14 +270,6 @@ function AnnotationCreation(props) { }); }; - /** */ - const { - annotation, - closeCompanionWindow, - id, - windowId, - } = props; - const { manifestNetwork, textBody, @@ -351,13 +288,13 @@ function AnnotationCreation(props) { imageEvent, } = toolState; - const mediaIsVideo = props.mediaVideo !== 'undefined'; + const mediaIsVideo = mediaVideo !== undefined; if (mediaIsVideo && valueTime) { valueTime[0] = tstart; valueTime[1] = tend; } - const videoDuration = props.mediaVideo ? props.mediaVideo.props.canvas.__jsonld.duration : 0; + const videoDuration = mediaVideo ? mediaVideo.props.canvas.__jsonld.duration : 0; // TODO: L'erreur de "Ref" sur l'ouverture d'une image vient d'ici et plus particulièrement // du useEffect qui prend en dépedance [overlay.containerWidth, overlay.canvasWidth] const videoref = VideosReferences.get(windowId); @@ -365,9 +302,23 @@ function AnnotationCreation(props) { let overlay = null; if (videoref) { overlay = videoref.canvasOverlay; - } - if (osdref) { - console.debug('osdref', osdref); + } else { + if (osdref) { + console.debug('osdref', osdref); + overlay = { + canvasHeight: osdref.current.canvas.clientHeight, + canvasWidth: osdref.current.canvas.clientWidth, + containerHeight: osdref.current.canvas.clientHeight, + containerWidth: osdref.current.canvas.clientWidth, + }; + } else { + overlay = { + canvasHeight: 500, + canvasWidth: 1000, + containerHeight: 500, + containerWidth: 1000, + }; + } } /** Change scale from container / canva */ @@ -395,7 +346,7 @@ function AnnotationCreation(props) { closed={closedMode === 'closed'} updateGeometry={updateGeometry} windowId={windowId} - player={mediaIsVideo ? props.mediaVideo : OSDReferences.get(windowId)} + player={mediaIsVideo ? mediaVideo : OSDReferences.get(windowId)} // we need to pass the width and height of the image to the annotation drawing component width={overlay ? overlay.containerWidth : 1920} height={overlay ? overlay.containerHeight : 1080} @@ -407,7 +358,7 @@ function AnnotationCreation(props) { setColorToolFromCurrentShape={setColorToolFromCurrentShape} drawingState={drawingState} isMouseOverSave={isMouseOverSave} - mediaVideo={props.mediaVideo} + mediaVideo={mediaVideo} setDrawingState={setDrawingState} /> <StyledForm> @@ -445,14 +396,13 @@ function AnnotationCreation(props) { mediaIsVideo={mediaIsVideo} videoDuration={videoDuration} value={valueTime} - handleChangeTime={handleChangeTime} windowid={windowId} - setTstartNow={setTstartNow} tstart={tstart} - updateTstart={updateTstart} - setTendNow={setTendNow} tend={tend} - updateTend={updateTend} + currentTime={currentTime} + setState={setState} + setCurrentTime={setCurrentTime} + setSeekTo={setSeekTo} /> </StyledTabPanel> <StyledTabPanel @@ -486,11 +436,11 @@ function AnnotationCreation(props) { </TabContext> <AnnotationFormFooter annotation={annotation} - canvases={props.canvases} + canvases={canvases} closeFormCompanionWindow={closeFormCompanionWindow} - config={props.config} + config={config} drawingState={drawingState} - receiveAnnotation={props.receiveAnnotation} + receiveAnnotation={receiveAnnotation} resetStateAfterSave={resetStateAfterSave} state={state} windowId={windowId} @@ -564,7 +514,6 @@ AnnotationCreation.defaultProps = { closeCompanionWindow: () => { }, currentTime: null, - paused: true, setCurrentTime: () => { }, setSeekTo: () => { diff --git a/src/AnnotationCreationUtils.js b/src/AnnotationCreationUtils.js index 57a8bc64fc1b58fdf9164ef4034cad9e8427cf85..703448c877b0249bfaf924e66796d530ecd268eb 100644 --- a/src/AnnotationCreationUtils.js +++ b/src/AnnotationCreationUtils.js @@ -1,6 +1,5 @@ /** Extract time information from annotation target */ export function timeFromAnnoTarget(annotarget) { - console.info('TODO proper time extraction from: ', annotarget); // TODO w3c media fragments: t=,10 t=5, const r = /t=([0-9.]+),([0-9.]+)/.exec(annotarget); if (!r || r.length !== 3) { @@ -11,7 +10,6 @@ export function timeFromAnnoTarget(annotarget) { /** Extract xywh from annotation target */ export function geomFromAnnoTarget(annotarget) { - console.info('TODO proper xywh extraction from: ', annotarget); const r = /xywh=((-?[0-9]+,?)+)/.exec(annotarget); if (!r || r.length !== 3) { return ''; diff --git a/src/EditTool.js b/src/EditTool.js index 9e076f78ba2484af5a149ae3cdd82432bc1396ab..58f6987788ad6a9832487fb1ee83fe99eaf37d74 100644 --- a/src/EditTool.js +++ b/src/EditTool.js @@ -132,9 +132,6 @@ class EditTool extends Component { /** */ render() { - - console.log('rendering edit tool'); - return ( <Tool onMouseDown={this.onMouseDown} diff --git a/src/WebAnnotation.js b/src/WebAnnotation.js index cfe8dacce9732796f24f052b7b96ebc7fe463161..d9c3031bb3ad978c0a1b118c54426b7f4b144e04 100644 --- a/src/WebAnnotation.js +++ b/src/WebAnnotation.js @@ -10,8 +10,6 @@ export default class WebAnnotation { this.body = body; this.drawingState = drawingStateSerialized; this.target = target; - - console.log('WebAnnotation constructor', this); } /** */ @@ -27,7 +25,6 @@ export default class WebAnnotation { const result = this; - console.log('WebAnnotation toJson', result); return result; } diff --git a/src/annotationForm/AnnotationDrawing.js b/src/annotationForm/AnnotationDrawing.js index d4506dbf77fdcbf72f177cff0f9306ec879ba794..de2b53c2f3cefa8dffee6856220c858174260938 100644 --- a/src/annotationForm/AnnotationDrawing.js +++ b/src/annotationForm/AnnotationDrawing.js @@ -11,10 +11,10 @@ import { OSDReferences } from 'mirador/dist/es/src/plugins/OSDReferences'; // eslint-disable-next-line import/no-extraneous-dependencies import { VideosReferences } from 'mirador/dist/es/src/plugins/VideosReferences'; import ParentComponent from './AnnotationFormOverlay/KonvaDrawing/shapes/ParentComponent'; -import {OVERLAY_TOOL, SHAPES_TOOL} from '../AnnotationCreationUtils'; +import { OVERLAY_TOOL, SHAPES_TOOL } from '../AnnotationCreationUtils'; /** All the stuff to draw on the canvas */ -function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { - const { height, width } = props.mediaVideo ? props.mediaVideo.ref.current : 0; +function AnnotationDrawing({ drawingState, setDrawingState, height, width, ...props }) { + useEffect(() => { const overlay = props.mediaVideo ? props.mediaVideo.ref.current : null; @@ -47,7 +47,6 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { const { fillColor, strokeColor, strokeWidth } = props; - useEffect(() => { // Perform an action when fillColor, strokeColor, or strokeWidth change // update current shape @@ -110,7 +109,6 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { const onTransform = (evt) => { const modifiedshape = evt.target.attrs; - console.log('modifiedshape', modifiedshape); const shape = drawingState.shapes.find((s) => s.id === modifiedshape.id); Object.assign(shape, modifiedshape); @@ -130,10 +128,10 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { const handleDragStart = (evt) => { const modifiedshape = evt.currentTarget.attrs; - setDrawingState({ - ...drawingState, - currentShape: drawingState.shapes.find((s) => s.id === modifiedshape.id), - }); + setDrawingState({ + ...drawingState, + currentShape: drawingState.shapes.find((s) => s.id === modifiedshape.id), + }); }; /** */ @@ -220,8 +218,8 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { y: pos.y, }; setDrawingState({ - isDrawing: true, currentShape: shape, + isDrawing: true, shapes: [...drawingState.shapes, shape], }); break; @@ -243,8 +241,8 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { y: pos.y, }; setDrawingState({ - isDrawing: true, currentShape: shape, + isDrawing: true, shapes: [...drawingState.shapes, shape], }); break; @@ -358,7 +356,6 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { pos.x /= props.scale; pos.y /= props.scale; - switch (props.activeTool) { case SHAPES_TOOL.RECTANGLE: updateCurrentShapeInShapes({ @@ -380,8 +377,8 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { ...drawingState.currentShape, height: pos.y - drawingState.currentShape.y, radiusX: (pos.x - drawingState.currentShape.x) / 2, - width: pos.x - drawingState.currentShape.x, radiusY: (pos.y - drawingState.currentShape.y) / 2, + width: pos.x - drawingState.currentShape.x, }); break; @@ -405,12 +402,12 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { const arrowShape = {}; // update points arrowShape.points = [drawingState.currentShape.points[0], drawingState.currentShape.points[1], pos.x, pos.y]; - arrowShape.id =drawingState.currentShape.id; - arrowShape.type =drawingState.currentShape.type; - arrowShape.pointerLength =drawingState.currentShape.pointerLength; - arrowShape.pointerWidth =drawingState.currentShape.pointerWidth; - arrowShape.x =drawingState.currentShape.x; - arrowShape.y =drawingState.currentShape.y; + arrowShape.id = drawingState.currentShape.id; + arrowShape.type = drawingState.currentShape.type; + arrowShape.pointerLength = drawingState.currentShape.pointerLength; + arrowShape.pointerWidth = drawingState.currentShape.pointerWidth; + arrowShape.x = drawingState.currentShape.x; + arrowShape.y = drawingState.currentShape.y; arrowShape.fill = props.fillColor; arrowShape.stroke = props.strokeColor; arrowShape.strokeWidth = props.strokeWidth; @@ -436,7 +433,7 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { } // For these cases, the action is similar: stop drawing and add the shape setDrawingState({ - ... drawingState, + ...drawingState, isDrawing: false, }); } catch (error) { @@ -497,32 +494,22 @@ function AnnotationDrawing({ drawingState, setDrawingState, ...props }) { if (osdref && videoref) { throw new Error('Unhandled case: both OpenSeadragon (image viewer) and video player on the same canvas'); } - const container = osdref ? osdref.current.element : videoref.ref.current.parentElement; + const container = osdref ? osdref.current.container : videoref.ref.current.parentElement; return ReactDOM.createPortal(drawKonvas(), container); } AnnotationDrawing.propTypes = { + activeTool: PropTypes.string.isRequired, + closed: PropTypes.bool.isRequired, drawingState: PropTypes.object.isRequired, - activeTool: PropTypes.string, - closed: PropTypes.bool, - fillColor: PropTypes.string, - selectedShapeId: PropTypes.string, - strokeColor: PropTypes.string, - strokeWidth: PropTypes.number, + fillColor: PropTypes.string.isRequired, + selectedShapeId: PropTypes.string.isRequired, + strokeColor: PropTypes.string.isRequired, + strokeWidth: PropTypes.number.isRequired, svg: PropTypes.func.isRequired, updateGeometry: PropTypes.func.isRequired, windowId: PropTypes.string.isRequired, }; -AnnotationDrawing.defaultProps = { - activeTool: null, - closed: true, - fillColor: 'red', - selectedShapeId: null, - strokeColor: '#00BFFF', - strokeWidth: 1, - svg: null, -}; - export default AnnotationDrawing; diff --git a/src/annotationForm/AnnotationFormFooter.js b/src/annotationForm/AnnotationFormFooter.js index f7beb0e2fb1713bb8a77806435b3d4c2d2fd21ab..cf5b2051ae99b8e835e41866a93b6d4c322abeb6 100644 --- a/src/annotationForm/AnnotationFormFooter.js +++ b/src/annotationForm/AnnotationFormFooter.js @@ -6,7 +6,7 @@ import { v4 as uuid } from 'uuid'; import { saveAnnotationInEachCanvas, } from '../AnnotationCreationUtils'; -import { secondsToHMS } from '../utils'; +import { removeHTMLTags, secondsToHMS } from '../utils'; import { getKonvaAsDataURL, } from './AnnotationFormOverlay/KonvaDrawing/KonvaUtils'; @@ -32,7 +32,6 @@ function AnnotationFormFooter({ * Validate form and save annotation */ const submitAnnotationForm = async (e) => { - console.log('submitForm'); e.preventDefault(); // TODO Possibly problem of syncing // TODO Improve this code @@ -59,7 +58,16 @@ function AnnotationFormFooter({ xywh, // TODO retrouver calcul de xywh }; - const annotationText = (!textBody.length && target.t) ? `${secondsToHMS(tstart)} -> ${secondsToHMS(tend)}` : textBody; + let annotationText; + if (textBody.length == 0 || removeHTMLTags(textBody).length == 0) { + if (target.t) { + annotationText = `${new Date().toLocaleString()} - ${secondsToHMS(tstart)} -> ${secondsToHMS(tend)}`; + } else { + annotationText = new Date().toLocaleString(); + } + } else { + annotationText = textBody; + } let id = annotation?.id ? annotation.id : `https://${uuid()}`; id = id.split('#')[0]; @@ -82,9 +90,6 @@ function AnnotationFormFooter({ type: 'Annotation', // Will be updated in saveAnnotationInEachCanvas }; - console.log('Annotation to save:', annotationToSaved); - console.log('target:', target); - const isNewAnnotation = !annotation; // Save jpg image of the drawing in a data url diff --git a/src/annotationForm/AnnotationFormTarget.js b/src/annotationForm/AnnotationFormTarget.js index 72f080784861fed27d0005a075da55428bf5abb3..f411d06ebc2ea454c37d468997b89f4c370db16c 100644 --- a/src/annotationForm/AnnotationFormTarget.js +++ b/src/annotationForm/AnnotationFormTarget.js @@ -60,8 +60,89 @@ const StyledToggleButton = styled(ToggleButton)(({ theme }) => ({ /** Form part with time mangement, dual slider + double input. Mange Tstart and Tend value */ function AnnotationFormTarget({ - videoDuration, value, handleChangeTime, windowid, setTstartNow, tstart, updateTstart, setTendNow, tend, updateTend, mediaIsVideo, + videoDuration, + value, + windowid, + tstart, + tend, + mediaIsVideo, + setState, + currentTime, + setSeekTo, + setCurrentTime, }) { + + /** set annotation start time to current time */ + const setTstartNow = () => { + setState((prevState) => ({ + ...prevState, + tstart: Math.floor(currentTime), + })); + }; + + /** set annotation end time to current time */ + const setTendNow = () => { + setState((prevState) => ({ + ...prevState, + tend: Math.floor(currentTime), + })); + }; + + /** + * @param {number} newValueTime + */ + const setValueTime = (newValueTime) => { + setState((prevState) => ({ + ...prevState, + valueTime: newValueTime, + })); + }; + + /** + * Change from slider + * @param {Event} event + * @param {number} newValueTime + */ + const handleChangeTime = (event, newValueTime) => { + const timeStart = newValueTime[0]; + const timeEnd = newValueTime[1]; + updateTstart(timeStart); + updateTend(timeEnd); + seekToTstart(); + setValueTime(newValueTime); + }; + + /** Change from Tstart HMS Input */ + const updateTstart = (value) => { + if (value > tend) { + return; + } + setState((prevState) => ({ + ...prevState, + tstart: value, + ...setSeekTo(value), + ...setCurrentTime(value), + + })); + }; + + /** update annotation end time */ + const updateTend = (value) => { + setState((prevState) => ({ + ...prevState, + tend: value, + })); + }; + + // eslint-disable-next-line require-jsdoc + const seekToTstart = () => { + setState((prevState) => ({ + ...prevState, + ...setSeekTo(prevState.tstart), + ...setCurrentTime(prevState.tstart), + })); + }; + return ( <> { mediaIsVideo && ( @@ -132,17 +213,16 @@ function AnnotationFormTarget({ } AnnotationFormTarget.propTypes = { - handleChangeTime: PropTypes.func.isRequired, mediaIsVideo: PropTypes.bool.isRequired, - setTendNow: PropTypes.func.isRequired, - setTstartNow: PropTypes.func.isRequired, tend: PropTypes.any.isRequired, tstart: PropTypes.number.isRequired, - updateTend: PropTypes.func.isRequired, - updateTstart: PropTypes.func.isRequired, value: PropTypes.arrayOf(PropTypes.number).isRequired, videoDuration: PropTypes.any.isRequired, windowid: PropTypes.any.isRequired, + currentTime: PropTypes.any.isRequired, + setSeekTo: PropTypes.func.isRequired, + setState: PropTypes.func.isRequired, + setCurrentTime: PropTypes.func.isRequired, }; export default AnnotationFormTarget; diff --git a/src/utils.js b/src/utils.js index f30b3dafd1afc7f8ef6194fb9ba2bcd1d0e8aeef..855531c28f5c6452dd7f0922d21b1893e6246c3b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -38,3 +38,8 @@ export const isValidUrl = (string) => { return false; } }; + +export const removeHTMLTags = (htmlString) => { + const doc = new DOMParser().parseFromString(htmlString, 'text/html'); + return doc.body.textContent || ''; +};