diff options
Diffstat (limited to 'animism-align/frontend/views/align/components')
7 files changed, 110 insertions, 143 deletions
diff --git a/animism-align/frontend/views/align/components/annotations/annotation.form.js b/animism-align/frontend/views/align/components/annotations/annotation.form.js new file mode 100644 index 0000000..9b02478 --- /dev/null +++ b/animism-align/frontend/views/align/components/annotations/annotation.form.js @@ -0,0 +1,95 @@ +import React, { Component } from 'react' +// import { Link } from 'react-router-dom' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' + +import actions from '../../../../actions' +// import * as alignActions from '../align.actions' + +import { ZOOM_STEPS } from '../../constants' +import { clamp } from '../../../../util' +import { timeToPosition } from '../../align.util' +import { Select } from '../../../../common' + +const TIMESTAMP_TYPES = ['sentence', 'header'].map(name => ({ name, label: name })) + +class AnnotationForm extends Component { + state = { + data: {}, + } + constructor(props){ + super(props) + this.handleChange = this.handleChange.bind(this) + this.handleSelect = this.handleSelect.bind(this) + } + componentDidMount(){ + this.setState({ + data: { ...this.props.annotation }, + }) + } + componentDidUpdate(prevProps){ + if (this.props.annotation !== prevProps.annotation) { + this.setState({ + data: { ...this.props.annotation }, + }) + } + } + handleChange(e) { + const { name, value } = e.target + this.handleSelect(name, value) + } + handleSelect(name, value) { + this.setState({ + data: { + ...this.state.data, + [name]: value, + } + }) + } + render() { + const { timeline } = this.props + const { data } = this.state + if (!data.start_ts) return <div></div> + return ( + <div + className='annotationForm' + style={{ + top: timeToPosition(data.start_ts, timeline), + }} + > + <div> + <textarea + value={data.text} + onChange={this.handleChange} + /> + </div> + <div className='row'> + <Select + name='type' + selected={data.type} + options={TIMESTAMP_TYPES} + defaultOption='text' + onChange={this.handleSelect} + /> + <button>Save</button> + </div> + </div> + ) + } +} + + +/* +- get the first sentence from the text +- display the form at that point +*/ + +const mapStateToProps = state => ({ + annotation: state.align.annotation, + timeline: state.align.timeline, +}) + +const mapDispatchToProps = dispatch => ({ +}) + +export default connect(mapStateToProps, mapDispatchToProps)(AnnotationForm) diff --git a/animism-align/frontend/views/align/components/timeline.component.js b/animism-align/frontend/views/align/components/timeline.component.js deleted file mode 100644 index 3b12cb5..0000000 --- a/animism-align/frontend/views/align/components/timeline.component.js +++ /dev/null @@ -1,129 +0,0 @@ -import React, { Component } from 'react' -// import { Link } from 'react-router-dom' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' - -import actions from '../../../actions' -// import * as alignActions from '../align.actions' - -import Waveform from './waveform.component' -import Ticks from './ticks.component' -import Cursor from './cursor.component' -import PlayButton from './playButton.component' -import PlayCursor from './playCursor.component' - -import { ZOOM_STEPS } from '../constants' -import { clamp } from '../../../util' - -class Timeline extends Component { - constructor(props){ - super(props) - this.handleKeydown = this.handleKeydown.bind(this) - this.handleMouseMove = this.handleMouseMove.bind(this) - this.handleWheel = this.handleWheel.bind(this) - this.handleClick = this.handleClick.bind(this) - } - componentDidMount() { - this.bind() - } - componentWillUnmount() { - this.unbind() - } - bind() { - document.addEventListener('keydown', this.handleKeydown) - } - unbind() { - document.removeEventListener('keydown', this.handleKeydown) - } - handleKeydown(e) { - if (document.activeElement !== document.body) { - return - } - if (e.shiftKey) { - switch (e.keyCode) { - case 187: // plus - actions.align.setZoom(this.props.timeline.zoom - 1) - break - case 189: // minus - actions.align.setZoom(this.props.timeline.zoom + 1) - break - } - } else { - console.log(e.keyCode) - switch (e.keyCode) { - case 32: // spacebar - actions.audio.toggle() - break - case 38: // up - actions.audio.jump(- ZOOM_STEPS[this.props.timeline.zoom] * 0.1) - break - case 40: // down - actions.audio.jump(ZOOM_STEPS[this.props.timeline.zoom] * 0.1) - break - } - } - } - handleWheel(e) { - let { start_ts, zoom, duration } = this.props.timeline - let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step - let widthTimeDuration = window.innerHeight * secondsPerPixel // secs per pixel - - start_ts = clamp(start_ts + e.deltaY * ZOOM_STEPS[zoom], 0, Math.max(0, duration - widthTimeDuration / 2)) - if (e.shiftKey) { - if (Math.abs(e.deltaY) < 2) return - if (e.deltaY > 0) { - actions.align.throttledSetZoom(this.props.timeline.zoom + 1) - } else { - actions.align.throttledSetZoom(this.props.timeline.zoom - 1) - } - } else if (e.altKey) { - actions.audio.seek(start_ts) - } else { - actions.align.setScrollPosition(start_ts) - } - } - handleMouseMove(e) { - const cursor_ts = positionToTime(e.pageY, this.props.timeline) - actions.align.setCursor(cursor_ts) - } - handleClick(e) { - const play_ts = positionToTime(e.pageY, this.props.timeline) - actions.audio.seek(play_ts) - } - render() { - return ( - <div - className='timeline' - onWheel={this.handleWheel} - onMouseMove={this.handleMouseMove} - > - <Waveform onClick={this.handleClick} /> - <Ticks timeline={this.props.timeline} /> - <Cursor timeline={this.props.timeline} /> - <PlayCursor /> - <PlayButton /> - </div> - ) - } -} - -const positionToTime = (y, { start_ts, zoom, duration }) => { - const secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 - const widthTimeDuration = window.innerHeight * secondsPerPixel - - const timeMin = start_ts - const timeMax = Math.min(start_ts + widthTimeDuration, duration) - const timeWidth = timeMax - timeMin - - return clamp(y * secondsPerPixel + start_ts, 0, timeMax) -} - -const mapStateToProps = state => ({ - timeline: state.align.timeline, -}) - -const mapDispatchToProps = dispatch => ({ - // alignActions: bindActionCreators({ ...alignActions }, dispatch), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(Timeline) diff --git a/animism-align/frontend/views/align/components/cursor.component.js b/animism-align/frontend/views/align/components/timeline/cursor.component.js index a5ad438..f621b37 100644 --- a/animism-align/frontend/views/align/components/cursor.component.js +++ b/animism-align/frontend/views/align/components/timeline/cursor.component.js @@ -1,12 +1,13 @@ import React, { Component } from 'react' -import { ZOOM_STEPS } from '../constants' -import { timestamp } from '../../../util' +import { ZOOM_STEPS } from '../../constants' +import { timestamp } from '../../../../util' -const Cursor = ({ timeline }) => { +const Cursor = ({ timeline, annotation }) => { const { start_ts, zoom, cursor_ts, duration } = timeline + const ts = annotation.start_ts || cursor_ts const secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 - const y = (cursor_ts - start_ts) / secondsPerPixel + const y = (ts - start_ts) / secondsPerPixel return ( <div className='cursor' @@ -16,7 +17,7 @@ const Cursor = ({ timeline }) => { > <div className='line' /> <div className='tickLabel'> - {timestamp(cursor_ts, 1)} + {timestamp(ts, 1)} </div> </div> ) diff --git a/animism-align/frontend/views/align/components/playButton.component.js b/animism-align/frontend/views/align/components/timeline/playButton.component.js index fcb1422..486eaee 100644 --- a/animism-align/frontend/views/align/components/playButton.component.js +++ b/animism-align/frontend/views/align/components/timeline/playButton.component.js @@ -3,11 +3,11 @@ import React, { Component } from 'react' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' -import actions from '../../../actions' +import actions from '../../../../actions' // import * as alignActions from '../align.actions' -import { ZOOM_STEPS } from '../constants' -import { clamp } from '../../../util' +import { ZOOM_STEPS } from '../../constants' +import { clamp } from '../../../../util' const PlayButton = ({ audio }) => { return ( diff --git a/animism-align/frontend/views/align/components/playCursor.component.js b/animism-align/frontend/views/align/components/timeline/playCursor.component.js index f191bb1..71e6a3a 100644 --- a/animism-align/frontend/views/align/components/playCursor.component.js +++ b/animism-align/frontend/views/align/components/timeline/playCursor.component.js @@ -3,8 +3,8 @@ import React, { Component } from 'react' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' -import { ZOOM_STEPS } from '../constants' -import { timestamp } from '../../../util' +import { ZOOM_STEPS } from '../../constants' +import { timestamp } from '../../../../util' const PlayCursor = ({ timeline, audio }) => { const { start_ts, zoom, duration } = timeline diff --git a/animism-align/frontend/views/align/components/ticks.component.js b/animism-align/frontend/views/align/components/timeline/ticks.component.js index 55821ae..72f9bd0 100644 --- a/animism-align/frontend/views/align/components/ticks.component.js +++ b/animism-align/frontend/views/align/components/timeline/ticks.component.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' -import { ZOOM_STEPS, ZOOM_LABEL_STEPS, ZOOM_TICK_STEPS } from '../constants' -import { timestamp } from '../../../util' +import { ZOOM_STEPS, ZOOM_LABEL_STEPS, ZOOM_TICK_STEPS } from '../../constants' +import { timestamp } from '../../../../util' export default class Ticks extends Component { render() { diff --git a/animism-align/frontend/views/align/components/waveform.component.js b/animism-align/frontend/views/align/components/timeline/waveform.component.js index e454623..128204a 100644 --- a/animism-align/frontend/views/align/components/waveform.component.js +++ b/animism-align/frontend/views/align/components/timeline/waveform.component.js @@ -3,10 +3,10 @@ import React, { Component } from 'react' // import { bindActionCreators } from 'redux' import { connect } from 'react-redux' -import actions from '../../../actions' +import actions from '../../../../actions' // import * as uploadActions from './upload.actions' -import { WAVEFORM_SIZE, ZOOM_STEPS, ZOOM_LABEL_STEPS, ZOOM_TICK_STEPS } from '../constants' +import { WAVEFORM_SIZE, ZOOM_STEPS, ZOOM_LABEL_STEPS, ZOOM_TICK_STEPS } from '../../constants' class Waveform extends Component { constructor(props){ |
