diff options
Diffstat (limited to 'animism-align/frontend/views/align/components/annotations')
10 files changed, 0 insertions, 541 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 deleted file mode 100644 index 01b1663..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotation.form.js +++ /dev/null @@ -1,183 +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 { ZOOM_STEPS } from '../../constants' -import { clamp, timestamp, capitalize } from '../../../../util' -import { timeToPosition } from '../../align.util' -import { Select } from '../../../../common' - -import { - AnnotationFormVideo, - AnnotationFormImage, -} from './annotationForms' - -const ANNOTATION_TYPES = [ - 'sentence', 'header', 'paragraph_end', 'video', 'image', 'image_carousel', -].map(name => ({ name, label: capitalize(name.replace('_', ' ')) })) - -class AnnotationForm extends Component { - constructor(props){ - super(props) - this.handleChange = this.handleChange.bind(this) - this.handleSelect = this.handleSelect.bind(this) - this.handleSettingsSelect = this.handleSettingsSelect.bind(this) - this.handleKeyDown = this.handleKeyDown.bind(this) - this.handleSubmit = this.handleSubmit.bind(this) - this.handleDestroy = this.handleDestroy.bind(this) - this.textareaRef = React.createRef() - } - componentDidMount() { - if (this.textareaRef && this.textareaRef.current) { - this.textareaRef.current.focus() - } - } - 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 - switch (e.keyCode) { - case 38: // up - e.preventDefault() - start_ts -= 0.1 - actions.align.updateAnnotationForm('start_ts', Math.max(0, start_ts)) - actions.audio.seek(start_ts) - actions.align.setCursor(start_ts) - break - case 40: // down - e.preventDefault() - start_ts += 0.1 - actions.align.updateAnnotationForm('start_ts', Math.max(0, start_ts)) - actions.audio.seek(start_ts) - actions.align.setCursor(start_ts) - break - case 83: // ctrl-S - e.preventDefault() - this.handleSubmit() - default: - break - } - } - handleChange(e) { - const { name, value } = e.target - this.handleSelect(name, value) - } - handleSelect(name, value) { - actions.align.updateAnnotationForm(name, value) - } - handleSettingsSelect(name, value) { - if (name.indexOf('_id') !== -1) value = parseInt(value) || 0 - actions.align.updateAnnotationSettings(name, value) - } - handleSubmit() { - const { annotation } = this.props - if (annotation.type === 'paragraph_end') { - annotation.text = '' - } - if (annotation.id === 'new') { - delete annotation.id - actions.annotation.create(annotation) - .then(response => { - console.log(response) - actions.align.hideAnnotationForm() - }) - } else { - actions.annotation.update(annotation) - .then(response => { - console.log(response) - actions.align.hideAnnotationForm() - }) - } - } - handleDestroy() { - const { annotation } = this.props - if (annotation.id === 'new') { - actions.align.hideAnnotationForm() - } else { - actions.annotation.destroy(annotation) - .then(response => { - console.log(response) - actions.align.hideAnnotationForm() - }) - } - } - render() { - const { timeline, annotation, media } = this.props - if (!annotation.start_ts) return <div></div> - return ( - <div - className='annotationForm' - style={{ - top: timeToPosition(annotation.start_ts, timeline), - }} - > - {this.renderButtons()} - {annotation.type === 'sentence' && this.renderTextarea()} - {annotation.type === 'header' && this.renderTextarea()} - {annotation.type === 'video' && - <AnnotationFormVideo annotation={annotation} media={media} handleSettingsSelect={this.handleSettingsSelect} /> - } - {annotation.type === 'image' && - <AnnotationFormImage annotation={annotation} media={media} handleSettingsSelect={this.handleSettingsSelect} /> - } - {annotation.type === 'image_carousel' && - <AnnotationFormImageCarousel annotation={annotation} media={media} handleSettingsSelect={this.handleSettingsSelect} /> - } - </div> - ) - } - renderButtons() { - const { annotation } = this.props - return ( - <div className='row buttons'> - <div> - <Select - name='type' - selected={annotation.type} - options={ANNOTATION_TYPES} - defaultOption='text' - onChange={this.handleSelect} - /> - <div className='ts'>{timestamp(annotation.start_ts, 1, true)}</div> - </div> - <div> - {annotation.id !== 'new' && <button onClick={this.handleDestroy}>Delete</button>} - <button onClick={this.handleSubmit}>Save</button> - </div> - </div> - ) - } - renderTextarea() { - const { annotation } = this.props - return ( - <div> - <textarea - name='text' - value={annotation.text} - onKeyDown={this.handleKeyDown} - onChange={this.handleChange} - ref={this.textareaRef} - /> - </div> - ) - } -} - -const mapStateToProps = state => ({ - annotation: state.align.annotation, - timeline: state.align.timeline, - media: state.media.index, -}) - -const mapDispatchToProps = dispatch => ({ -}) - -export default connect(mapStateToProps, mapDispatchToProps)(AnnotationForm) diff --git a/animism-align/frontend/views/align/components/annotations/annotation.index.js b/animism-align/frontend/views/align/components/annotations/annotation.index.js deleted file mode 100644 index 30dc7c0..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotation.index.js +++ /dev/null @@ -1,126 +0,0 @@ -import React, { Component } from 'react' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' - -import actions from '../../../../actions' - -import { ZOOM_STEPS, INNER_HEIGHT } from '../../constants' -import { clamp } from '../../../../util' -import { positionToTime, timeToPosition } from '../../align.util' - -import { AnnotationElementLookup } from './annotationTypes' - -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 = INNER_HEIGHT * secondsPerPixel // secs per pixel - - let timeMin = start_ts - 50.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]).reverse() - this.setState({ items }) - } - handleClick(e, annotation) { - e.stopPropagation() - if (e.shiftKey) { - e.preventDefault() - this.handleParagraphSelection(annotation, e.metaKey) - } - actions.audio.seek(annotation.start_ts) - actions.align.setSelectedAnnotation(annotation) - } - handleParagraphSelection(annotation, shouldClear) { - const { selected_paragraph_id } = this.props.timeline - if (!selected_paragraph_id || selected_paragraph_id === -1 || shouldClear) { - if (annotation.paragraph_id && !shouldClear) { - actions.align.setSelectedParagraph(annotation.paragraph_id) - } else { - actions.paragraph.create({ - type: 'paragraph', - start_ts: annotation.start_ts, - }).then(data => { - actions.align.setSelectedParagraph(data.res.id) - annotation.paragraph_id = data.res.id - actions.annotation.update(annotation) - }) - } - } else if (selected_paragraph_id !== annotation.paragraph_id) { - annotation.paragraph_id = selected_paragraph_id - actions.annotation.update(annotation) - } - } - handleDoubleClick(e, annotation) { - e.stopPropagation() - actions.align.showEditAnnotationForm(annotation) - } - render() { - const { timeline, media, annotationInForm, selectedAnnotation } = this.props - const { start_ts, zoom, selected_annotation_id } = timeline - const { items } = this.state - const className = (zoom < 2) - ? 'annotationIndex' - : (zoom < 3) - ? 'annotationIndex condensed' - : 'annotationIndex collapsed' - return ( - <div className={className}> - {items.map(annotation => { - if (annotationInForm && annotation.id === annotationInForm.id) { - return null - } - if (annotation.id === selected_annotation_id) { - annotation = selectedAnnotation - } - const { id, type, start_ts } = annotation - const AnnotationElement = AnnotationElementLookup[type] - const y = timeToPosition(start_ts, timeline) - return ( - <AnnotationElement - key={id} - y={y} - selected={annotation.id === selected_annotation_id} - annotation={annotation} - media={media} - onClick={this.handleClick} - onDoubleClick={this.handleDoubleClick} - /> - ) - })} - </div> - ) - } -} - -const mapStateToProps = state => ({ - timeline: state.align.timeline, - annotationInForm: state.align.annotation, - selectedAnnotation: state.align.selectedAnnotation, - index: state.annotation.index, - media: state.media.index.lookup, -}) - -const mapDispatchToProps = dispatch => ({ -}) - -export default connect(mapStateToProps, mapDispatchToProps)(AnnotationIndex) diff --git a/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.image.js b/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.image.js deleted file mode 100644 index e2df98b..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.image.js +++ /dev/null @@ -1,27 +0,0 @@ -import React, { Component } from 'react' - -import { Select } from '../../../../../common' - -export const AnnotationFormImage = ({ annotation, media, handleSettingsSelect }) => { - if (!media.lookup) return <div /> - const { lookup, order } = media - const image_list_items = order.filter(id => lookup[id].type === 'image').map(id => { - const image = lookup[id] - return { - name: image.id, - label: image.author + ' - ' + image.title - } - }) - return ( - <div> - <Select - name='media_id' - className="media_id" - selected={annotation.settings.media_id} - options={image_list_items} - defaultOption='Choose an image' - onChange={handleSettingsSelect} - /> - </div> - ) -} diff --git a/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.video.js b/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.video.js deleted file mode 100644 index 9302ba4..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.video.js +++ /dev/null @@ -1,27 +0,0 @@ -import React, { Component } from 'react' - -import { Select } from '../../../../../common' - -export const AnnotationFormVideo = ({ annotation, media, handleSettingsSelect }) => { - if (!media.lookup) return <div /> - const { lookup, order } = media - const video_list_items = order.filter(id => lookup[id].type === 'video').map(id => { - const video = lookup[id] - return { - name: video.id, - label: video.author + ' - ' + video.title - } - }) - return ( - <div> - <Select - name='media_id' - className="media_id" - selected={annotation.settings.media_id} - options={video_list_items} - defaultOption='Choose a video' - onChange={handleSettingsSelect} - /> - </div> - ) -} diff --git a/animism-align/frontend/views/align/components/annotations/annotationForms/index.js b/animism-align/frontend/views/align/components/annotations/annotationForms/index.js deleted file mode 100644 index 1411efc..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationForms/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import { - AnnotationFormVideo, -} from './annotationForm.video' - -import { - AnnotationFormImage, -} from './annotationForm.image' - -export { - AnnotationFormImage, - AnnotationFormVideo, -} diff --git a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.image.js b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.image.js deleted file mode 100644 index c3e0c22..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.image.js +++ /dev/null @@ -1,33 +0,0 @@ -import React, { Component } from 'react' - -import { thumbnailURL } from '../../../align.util' - -import { checkAnnotationMediaNotReady, AnnotationMediaLoading } from './annotationTypes.util' - -export const AnnotationImage = ({ y, annotation, media, selected, onClick, onDoubleClick }) => { - const { start_ts, text } = annotation - const className = selected ? 'annotation media image selected' : 'annotation media image' - if (checkAnnotationMediaNotReady(annotation, media)) { - return <AnnotationMediaLoading y={y} className={className} onClick={onClick} onDoubleClick={onDoubleClick} /> - } - const data = media[annotation.settings.media_id] - return ( - <div - className={className} - style={{ top: y }} - onClick={e => onClick(e, annotation)} - onDoubleClick={e => onDoubleClick(e, annotation)} - > - <div className='img'> - <img src={thumbnailURL(data)} alt={data.title} /> - </div> - <div className='meta center'> - <div> - <i>{data.title}</i><br /> - {data.author}<br /> - {data.date} - </div> - </div> - </div> - ) -} diff --git a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.text.js b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.text.js deleted file mode 100644 index be4674f..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.text.js +++ /dev/null @@ -1,49 +0,0 @@ -import React, { Component } from 'react' - -export const AnnotationSentence = ({ y, annotation, selected, onClick, onDoubleClick }) => { - const { start_ts, text, paragraph_id } = annotation - let className = !paragraph_id - ? 'annotation sentence' - : (paragraph_id % 2) - ? 'annotation sentence odd' - : 'annotation sentence even' - if (selected) className += ' selected' - return ( - <div - className={className} - style={{ top: y }} - onClick={e => onClick(e, annotation)} - onDoubleClick={e => onDoubleClick(e, annotation)} - dangerouslySetInnerHTML={{ __html: text }} - /> - ) -} - -export const AnnotationHeader = ({ y, annotation, selected, onClick, onDoubleClick }) => { - const { start_ts, text } = annotation - const className = selected ? 'annotation header selected' : 'annotation header' - return ( - <div - className={className} - style={{ top: y }} - onClick={e => onClick(e, annotation)} - onDoubleClick={e => onDoubleClick(e, annotation)} - > - {text} - </div> - ) -} - -export const AnnotationParagraphEnd = ({ y, annotation, selected, onClick, onDoubleClick }) => { - const { start_ts, text } = annotation - const className = selected ? 'annotation paragraph_end selected' : 'annotation paragraph_end' - return ( - <div - className={className} - style={{ top: y }} - onClick={e => onClick(e, annotation)} - onDoubleClick={e => onDoubleClick(e, annotation)} - > - </div> - ) -} diff --git a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.util.js b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.util.js deleted file mode 100644 index 17abebd..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.util.js +++ /dev/null @@ -1,28 +0,0 @@ -import React, { Component } from 'react' - -export const checkAnnotationMediaNotReady = (annotation, media) => { - return (!media) || (!(annotation.settings.media_id in media)) -} - -export const AnnotationMediaLoading = ({ y, className, onClick, onDoubleClick }) => { - if (!media) { - return ( - <div - className={className} - style={{ top: y }} - onClick={e => onClick(e, annotation)} - onDoubleClick={e => onDoubleClick(e, annotation)} - >LOADING...</div> - ) - } - if (!(annotation.settings.media_id in media)) { - return ( - <div - className={className} - style={{ top: y }} - onClick={e => onClick(e, annotation)} - onDoubleClick={e => onDoubleClick(e, annotation)} - >MEDIA NOT FOUND</div> - ) - } -} diff --git a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.video.js b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.video.js deleted file mode 100644 index dc4f469..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.video.js +++ /dev/null @@ -1,34 +0,0 @@ -import React, { Component } from 'react' - -import { thumbnailURL } from '../../../align.util' - -import { checkAnnotationMediaNotReady, AnnotationMediaLoading } from './annotationTypes.util' - -export const AnnotationVideo = ({ y, annotation, media, selected, onClick, onDoubleClick }) => { - const { start_ts, text } = annotation - const className = selected ? 'annotation media video selected' : 'annotation media video' - if (checkAnnotationMediaNotReady(annotation, media)) { - return <AnnotationMediaLoading y={y} className={className} onClick={onClick} onDoubleClick={onDoubleClick} /> - } - const data = media[annotation.settings.media_id] - return ( - <div - className={className} - style={{ top: y }} - onClick={e => onClick(e, annotation)} - onDoubleClick={e => onDoubleClick(e, annotation)} - > - <div className='img'> - <img src={thumbnailURL(data)} alt={data.title} /> - </div> - <div className='meta center'> - <div> - <i>{data.title}</i><br /> - {data.author}<br /> - {data.date} - </div> - </div> - </div> - ) -} - diff --git a/animism-align/frontend/views/align/components/annotations/annotationTypes/index.js b/animism-align/frontend/views/align/components/annotations/annotationTypes/index.js deleted file mode 100644 index 560063b..0000000 --- a/animism-align/frontend/views/align/components/annotations/annotationTypes/index.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react' - -import { - AnnotationSentence, AnnotationHeader, - AnnotationParagraphEnd, -} from './annotationTypes.text' - -import { - AnnotationVideo, -} from './annotationTypes.video' - -import { - AnnotationImage, -} from './annotationTypes.image' - -export const AnnotationElementLookup = { - sentence: React.memo(AnnotationSentence), - header: React.memo(AnnotationHeader), - paragraph_end: React.memo(AnnotationParagraphEnd), - video: React.memo(AnnotationVideo), - image: React.memo(AnnotationImage), -} |
