summaryrefslogtreecommitdiff
path: root/animism-align/frontend/views/align/components/annotations
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/views/align/components/annotations')
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.form.js6
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.index.js83
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.types.js40
3 files changed, 128 insertions, 1 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
index 9432948..b62c36e 100644
--- a/animism-align/frontend/views/align/components/annotations/annotation.form.js
+++ b/animism-align/frontend/views/align/components/annotations/annotation.form.js
@@ -24,9 +24,13 @@ class AnnotationForm extends Component {
this.handleSubmit = this.handleSubmit.bind(this)
}
handleKeyDown(e) {
+ if (e.keyCode === 27) { // escape
+ actions.align.hideAnnotationForm()
+ return
+ }
+ // console.log(e.keyCode)
if (!e.metaKey && !e.ctrlKey) return
let { start_ts } = this.props.annotation
- console.log(e.keyCode)
switch (e.keyCode) {
case 38: // up
e.preventDefault()
diff --git a/animism-align/frontend/views/align/components/annotations/annotation.index.js b/animism-align/frontend/views/align/components/annotations/annotation.index.js
new file mode 100644
index 0000000..7b562c2
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotation.index.js
@@ -0,0 +1,83 @@
+import React, { Component } from 'react'
+import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+
+import actions from '../../../../actions'
+
+import { ZOOM_STEPS } from '../../constants'
+import { clamp } from '../../../../util'
+import { positionToTime, timeToPosition } from '../../align.util'
+
+import { AnnotationElementLookup } from './annotation.types'
+
+class AnnotationIndex extends Component {
+ state = {
+ items: [],
+ }
+ constructor(props){
+ super(props)
+ this.handleClick = this.handleClick.bind(this)
+ }
+ componentDidUpdate(prevProps) {
+ if (this.props.index.loading) return
+ if (prevProps.timeline !== this.props.timeline || prevProps.index !== this.props.index) {
+ this.update()
+ }
+ }
+ update() {
+ let { timeline, index } = this.props
+ let { start_ts, zoom, duration } = this.props.timeline
+ const { order, lookup } = index
+
+ let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step
+ let widthTimeDuration = window.innerHeight * secondsPerPixel // secs per pixel
+
+ let timeMin = start_ts - 30.0
+ let timeMax = Math.min(start_ts + widthTimeDuration, duration)
+
+ const items = order.filter(id => {
+ const { start_ts: ts } = lookup[id]
+ return (timeMin < ts && ts < timeMax)
+ }).map(id => lookup[id])
+ this.setState({ items })
+ }
+ handleClick(annotation) {
+ actions.audio.seek(annotation.start_ts)
+ }
+ handleDoubleClick(annotation) {
+ actions.align.showEditAnnotationForm(annotation)
+ }
+ render() {
+ const { timeline } = this.props
+ const { start_ts } = timeline
+ const { items } = this.state
+ return (
+ <div className='annotationIndex'>
+ {items.map(annotation => {
+ const { id, type, start_ts } = annotation
+ const AnnotationElement = AnnotationElementLookup[type]
+ const y = timeToPosition(start_ts, timeline)
+ return (
+ <AnnotationElement
+ key={id}
+ y={y}
+ annotation={annotation}
+ onClick={this.handleClick}
+ onDoubleClick={this.handleDoubleClick}
+ />
+ )
+ })}
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+ timeline: state.align.timeline,
+ index: state.annotation.index,
+})
+
+const mapDispatchToProps = dispatch => ({
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(AnnotationIndex)
diff --git a/animism-align/frontend/views/align/components/annotations/annotation.types.js b/animism-align/frontend/views/align/components/annotations/annotation.types.js
new file mode 100644
index 0000000..465844f
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotation.types.js
@@ -0,0 +1,40 @@
+import React, { Component } from 'react'
+
+import actions from '../../../../actions'
+
+import { ZOOM_STEPS } from '../../constants'
+import { clamp } from '../../../../util'
+import { positionToTime, timeToPosition } from '../../align.util'
+
+export const AnnotationSentence = ({ y, annotation, onClick, onDoubleClick }) => {
+ const { start_ts, text } = annotation
+ return (
+ <div
+ className='annotation sentence'
+ style={{ top: y }}
+ onClick={() => onClick(annotation)}
+ onDoubleClick={() => onDoubleClick(annotation)}
+ >
+ {text}
+ </div>
+ )
+}
+
+export const AnnotationHeader = ({ y, annotation, onClick, onDoubleClick }) => {
+ const { start_ts, text } = annotation
+ return (
+ <div
+ className='annotation header'
+ style={{ top: y }}
+ onClick={() => onClick(annotation)}
+ onDoubleClick={() => onDoubleClick(annotation)}
+ >
+ {text}
+ </div>
+ )
+}
+
+export const AnnotationElementLookup = {
+ sentence: AnnotationSentence,
+ header: AnnotationHeader,
+} \ No newline at end of file