summaryrefslogtreecommitdiff
path: root/animism-align/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend')
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.form.js43
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.index.js2
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.types.js108
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.image.js27
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.video.js27
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationForms/index.js12
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.image.js33
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.text.js49
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.util.js28
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.video.js34
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotationTypes/index.js22
-rw-r--r--animism-align/frontend/views/paragraph/components/paragraphTypes/index.js16
-rw-r--r--animism-align/frontend/views/paragraph/components/paragraphTypes/paragraphTypes.text.js (renamed from animism-align/frontend/views/paragraph/components/paragraph.types.js)26
-rw-r--r--animism-align/frontend/views/paragraph/components/paragraphTypes/paragraphTypes.video.js19
-rw-r--r--animism-align/frontend/views/paragraph/containers/paragraphList.container.js2
15 files changed, 285 insertions, 163 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 53f640f..01b1663 100644
--- a/animism-align/frontend/views/align/components/annotations/annotation.form.js
+++ b/animism-align/frontend/views/align/components/annotations/annotation.form.js
@@ -11,8 +11,13 @@ 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',
+ 'sentence', 'header', 'paragraph_end', 'video', 'image', 'image_carousel',
].map(name => ({ name, label: capitalize(name.replace('_', ' ')) }))
class AnnotationForm extends Component {
@@ -105,7 +110,7 @@ class AnnotationForm extends Component {
}
}
render() {
- const { timeline, annotation } = this.props
+ const { timeline, annotation, media } = this.props
if (!annotation.start_ts) return <div></div>
return (
<div
@@ -117,7 +122,15 @@ class AnnotationForm extends Component {
{this.renderButtons()}
{annotation.type === 'sentence' && this.renderTextarea()}
{annotation.type === 'header' && this.renderTextarea()}
- {annotation.type === 'video' && this.renderVideo()}
+ {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>
)
}
@@ -156,30 +169,6 @@ class AnnotationForm extends Component {
</div>
)
}
- renderVideo() {
- const { annotation, media } = this.props
- 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={this.handleSettingsSelect}
- />
- </div>
- )
- }
}
const mapStateToProps = state => ({
diff --git a/animism-align/frontend/views/align/components/annotations/annotation.index.js b/animism-align/frontend/views/align/components/annotations/annotation.index.js
index b055d60..65de5dd 100644
--- a/animism-align/frontend/views/align/components/annotations/annotation.index.js
+++ b/animism-align/frontend/views/align/components/annotations/annotation.index.js
@@ -8,7 +8,7 @@ import { ZOOM_STEPS, INNER_HEIGHT } from '../../constants'
import { clamp } from '../../../../util'
import { positionToTime, timeToPosition } from '../../align.util'
-import { AnnotationElementLookup } from './annotation.types'
+import { AnnotationElementLookup } from './annotationTypes'
class AnnotationIndex extends Component {
state = {
diff --git a/animism-align/frontend/views/align/components/annotations/annotation.types.js b/animism-align/frontend/views/align/components/annotations/annotation.types.js
deleted file mode 100644
index 55cc3e7..0000000
--- a/animism-align/frontend/views/align/components/annotations/annotation.types.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import React, { Component } from 'react'
-
-import actions from '../../../../actions'
-
-import { ZOOM_STEPS } from '../../constants'
-import { clamp } from '../../../../util'
-import { positionToTime, timeToPosition, thumbnailURL } from '../../align.util'
-
-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>
- )
-}
-
-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 (!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>
- )
- }
- 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>
- )
-}
-
-
-export const AnnotationElementLookup = {
- sentence: React.memo(AnnotationSentence),
- header: React.memo(AnnotationHeader),
- paragraph_end: React.memo(AnnotationParagraphEnd),
- video: React.memo(AnnotationVideo),
-}
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
new file mode 100644
index 0000000..e2df98b
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.image.js
@@ -0,0 +1,27 @@
+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
new file mode 100644
index 0000000..9302ba4
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationForms/annotationForm.video.js
@@ -0,0 +1,27 @@
+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
new file mode 100644
index 0000000..1411efc
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationForms/index.js
@@ -0,0 +1,12 @@
+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
new file mode 100644
index 0000000..c3e0c22
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.image.js
@@ -0,0 +1,33 @@
+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
new file mode 100644
index 0000000..be4674f
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.text.js
@@ -0,0 +1,49 @@
+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
new file mode 100644
index 0000000..17abebd
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.util.js
@@ -0,0 +1,28 @@
+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
new file mode 100644
index 0000000..dc4f469
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationTypes/annotationTypes.video.js
@@ -0,0 +1,34 @@
+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
new file mode 100644
index 0000000..3a2fae1
--- /dev/null
+++ b/animism-align/frontend/views/align/components/annotations/annotationTypes/index.js
@@ -0,0 +1,22 @@
+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),
+}
diff --git a/animism-align/frontend/views/paragraph/components/paragraphTypes/index.js b/animism-align/frontend/views/paragraph/components/paragraphTypes/index.js
new file mode 100644
index 0000000..990c911
--- /dev/null
+++ b/animism-align/frontend/views/paragraph/components/paragraphTypes/index.js
@@ -0,0 +1,16 @@
+import React from 'react'
+
+import {
+ Paragraph, ParagraphHeader
+} from './paragraphTypes.text'
+
+import {
+ MediaVideo
+} from './paragraphTypes.video'
+
+export const ParagraphElementLookup = {
+ paragraph: React.memo(Paragraph),
+ blockquote: React.memo(Paragraph),
+ header: React.memo(ParagraphHeader),
+ video: React.memo(MediaVideo),
+}
diff --git a/animism-align/frontend/views/paragraph/components/paragraph.types.js b/animism-align/frontend/views/paragraph/components/paragraphTypes/paragraphTypes.text.js
index fe8158a..5f8dbc3 100644
--- a/animism-align/frontend/views/paragraph/components/paragraph.types.js
+++ b/animism-align/frontend/views/paragraph/components/paragraphTypes/paragraphTypes.text.js
@@ -1,7 +1,4 @@
import React, { Component } from 'react'
-import VimeoPlayer from '@u-wave/react-vimeo'
-
-import actions from '../../../actions'
export const Paragraph = ({ paragraph, selectedParagraph, selectedAnnotation, onAnnotationClick, onDoubleClick }) => {
let className = paragraph.type
@@ -37,26 +34,3 @@ export const ParagraphHeader = ({ paragraph, selectedParagraph, selectedAnnotati
</div>
)
}
-
-export const MediaVideo = ({ paragraph, media, selectedParagraph, selectedAnnotation, onAnnotationClick, onDoubleClick }) => {
- if (!media.lookup) return <div />
- const className = selectedParagraph ? 'media selected' : 'media'
- const annotation = paragraph.annotations[0]
- const item = media.lookup[annotation.settings.media_id]
- if (!item) return <div>Media not found: {annotation.settings.media_id}</div>
- return (
- <div
- className={className}
- onDoubleClick={e => onDoubleClick(e, paragraph)}
- >
- <VimeoPlayer video={item.url} autoplay muted width="650" />
- </div>
- )
-}
-
-export const ParagraphElementLookup = {
- paragraph: React.memo(Paragraph),
- blockquote: React.memo(Paragraph),
- header: React.memo(ParagraphHeader),
- video: React.memo(MediaVideo),
-}
diff --git a/animism-align/frontend/views/paragraph/components/paragraphTypes/paragraphTypes.video.js b/animism-align/frontend/views/paragraph/components/paragraphTypes/paragraphTypes.video.js
new file mode 100644
index 0000000..8e224f3
--- /dev/null
+++ b/animism-align/frontend/views/paragraph/components/paragraphTypes/paragraphTypes.video.js
@@ -0,0 +1,19 @@
+import React, { Component } from 'react'
+
+import VimeoPlayer from '@u-wave/react-vimeo'
+
+export const MediaVideo = ({ paragraph, media, selectedParagraph, selectedAnnotation, onAnnotationClick, onDoubleClick }) => {
+ if (!media.lookup) return <div />
+ const className = selectedParagraph ? 'media selected' : 'media'
+ const annotation = paragraph.annotations[0]
+ const item = media.lookup[annotation.settings.media_id]
+ if (!item) return <div>Media not found: {annotation.settings.media_id}</div>
+ return (
+ <div
+ className={className}
+ onDoubleClick={e => onDoubleClick(e, paragraph)}
+ >
+ <VimeoPlayer video={item.url} autoplay muted width="650" />
+ </div>
+ )
+}
diff --git a/animism-align/frontend/views/paragraph/containers/paragraphList.container.js b/animism-align/frontend/views/paragraph/containers/paragraphList.container.js
index fc1a687..deeb347 100644
--- a/animism-align/frontend/views/paragraph/containers/paragraphList.container.js
+++ b/animism-align/frontend/views/paragraph/containers/paragraphList.container.js
@@ -4,7 +4,7 @@ import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import actions from '../../../actions'
-import { ParagraphElementLookup } from '../components/paragraph.types'
+import { ParagraphElementLookup } from '../components/paragraphTypes'
const floatLT = (a,b) => ((a*10|0) < (b*10|0))
const floatLTE = (a,b) => ((a*10|0) === (b*10|0) || floatLT(a,b))