summaryrefslogtreecommitdiff
path: root/animism-align/frontend
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2020-07-22 18:28:07 +0200
committerJules Laplace <julescarbon@gmail.com>2020-07-22 18:28:07 +0200
commit2b14723d7b4e495a465049acec6838a6bbd907a8 (patch)
tree2553e5449fbe62b195a01631ae1a9d111592d7a1 /animism-align/frontend
parent390fdf840b6bda1c830af18c912db1234baa3ebb (diff)
display transcript with custom renderer
Diffstat (limited to 'animism-align/frontend')
-rw-r--r--animism-align/frontend/app/views/paragraph/containers/paragraphEditor.container.js3
-rw-r--r--animism-align/frontend/app/views/paragraph/paragraph.container.js2
-rw-r--r--animism-align/frontend/app/views/viewer/checklist/checklist.container.js (renamed from animism-align/frontend/app/views/viewer/containers/checklist.container.js)0
-rw-r--r--animism-align/frontend/app/views/viewer/nav/viewer.nav.js (renamed from animism-align/frontend/app/views/viewer/containers/viewer.nav.js)0
-rw-r--r--animism-align/frontend/app/views/viewer/nav/viewer.router.js (renamed from animism-align/frontend/app/views/viewer/containers/viewer.router.js)2
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js47
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js35
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js21
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/components/index.js22
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/transcript.container.js (renamed from animism-align/frontend/app/views/viewer/containers/transcript.container.js)18
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.container.js10
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.css63
12 files changed, 213 insertions, 10 deletions
diff --git a/animism-align/frontend/app/views/paragraph/containers/paragraphEditor.container.js b/animism-align/frontend/app/views/paragraph/containers/paragraphEditor.container.js
index 12ab618..c031d8a 100644
--- a/animism-align/frontend/app/views/paragraph/containers/paragraphEditor.container.js
+++ b/animism-align/frontend/app/views/paragraph/containers/paragraphEditor.container.js
@@ -27,7 +27,6 @@ class ParagraphEditor extends Component {
}
handleParagraphDoubleClick(e, paragraph) {
- console.log(e.target.parentNode)
let paragraphNode = e.target
if (!paragraphNode.classList.contains('paragraph')) {
paragraphNode = paragraphNode.parentNode
@@ -48,7 +47,7 @@ class ParagraphEditor extends Component {
render() {
// const { media } = this.props
- const { paragraphs, selectedParagraph, currentParagraph, currentAnnotation } = this.state
+ const { paragraphs, selectedParagraph, selectedParagraphOffset } = this.state
return (
<div className='paragraphs'>
<div className='content'>
diff --git a/animism-align/frontend/app/views/paragraph/paragraph.container.js b/animism-align/frontend/app/views/paragraph/paragraph.container.js
index 71af036..d0e9b86 100644
--- a/animism-align/frontend/app/views/paragraph/paragraph.container.js
+++ b/animism-align/frontend/app/views/paragraph/paragraph.container.js
@@ -56,7 +56,7 @@ class ParagraphContainer extends Component {
}
const mapStateToProps = state => ({
- loaded: !!state.annotation.lookup && !!state.paragraph.lookup && !!state.media.lookup
+ loaded: !!state.annotation.index.lookup && !!state.paragraph.index.lookup && !!state.media.index.lookup
})
const mapDispatchToProps = dispatch => ({
diff --git a/animism-align/frontend/app/views/viewer/containers/checklist.container.js b/animism-align/frontend/app/views/viewer/checklist/checklist.container.js
index 5d35e7c..5d35e7c 100644
--- a/animism-align/frontend/app/views/viewer/containers/checklist.container.js
+++ b/animism-align/frontend/app/views/viewer/checklist/checklist.container.js
diff --git a/animism-align/frontend/app/views/viewer/containers/viewer.nav.js b/animism-align/frontend/app/views/viewer/nav/viewer.nav.js
index e1613b4..e1613b4 100644
--- a/animism-align/frontend/app/views/viewer/containers/viewer.nav.js
+++ b/animism-align/frontend/app/views/viewer/nav/viewer.nav.js
diff --git a/animism-align/frontend/app/views/viewer/containers/viewer.router.js b/animism-align/frontend/app/views/viewer/nav/viewer.router.js
index b432302..e352af5 100644
--- a/animism-align/frontend/app/views/viewer/containers/viewer.router.js
+++ b/animism-align/frontend/app/views/viewer/nav/viewer.router.js
@@ -9,7 +9,7 @@ class ViewerRouter extends Component {
this.route()
}
route() {
- console.log(this.props.match.params.component)
+ // console.log(this.props.match.params.component)
switch (this.props.match.params.component) {
case 'transcript':
actions.viewer.showSection('transcript')
diff --git a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js
new file mode 100644
index 0000000..c2477ee
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js
@@ -0,0 +1,47 @@
+import React, { Component } from 'react'
+
+export const MediaCitation = ({ media }) => {
+ if (media.citation) {
+ return (
+ <span dangerouslySetInnerHTML={{ _html: media.citation }} />
+ )
+ }
+ console.log(media)
+ return (
+ <span>
+ {media.author}
+ {', '}
+ {media.pre_title}
+ <i>{media.title}</i>
+ {media.post_title}
+ {'. '}
+ {media.date && (
+ ' ' + media.date + '.'
+ )}
+ {media.medium && (
+ ' ' + media.medium + '.'
+ )}
+ {media.source && (
+ ' ' + media.source.trim()
+ )}
+ </span>
+ )
+}
+
+export const MediaImage = ({ paragraph, media, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => {
+ if (!media.lookup) return <div />
+ const className = currentParagraph ? 'media image current' : 'media image'
+ 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)}
+ >
+ {"["}
+ <MediaCitation media={item} />
+ {"]"}
+ </div>
+ )
+}
diff --git a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js
new file mode 100644
index 0000000..c2ebcd7
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.text.js
@@ -0,0 +1,35 @@
+import React, { Component } from 'react'
+
+export const Paragraph = ({ paragraph, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => {
+ let className = paragraph.type
+ if (className !== 'paragraph') className += ' paragraph'
+ if (currentParagraph) className += ' current'
+ return (
+ <div
+ className={className}
+ onDoubleClick={e => onDoubleClick(e, paragraph)}
+ >
+ {paragraph.annotations.map(annotation => (
+ <span
+ key={annotation.id}
+ className={annotation.id === currentAnnotation ? 'current' : ''}
+ onClick={e => onAnnotationClick(e, paragraph, annotation)}
+ dangerouslySetInnerHTML={{ __html: ' ' + annotation.text + ' ' }}
+ />
+ ))}
+ </div>
+ )
+}
+
+export const ParagraphHeader = ({ paragraph, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => {
+ let className = currentParagraph ? 'header current' : 'header'
+ const text = paragraph.annotations.map(annotation => annotation.text).join(' ')
+ return (
+ <div
+ className={className}
+ onDoubleClick={e => onDoubleClick(e, paragraph)}
+ >
+ {text}
+ </div>
+ )
+}
diff --git a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js
new file mode 100644
index 0000000..fe821eb
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js
@@ -0,0 +1,21 @@
+import React, { Component } from 'react'
+
+import { MediaCitation } from './elementTypes.image'
+
+export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => {
+ if (!media.lookup) return <div />
+ const className = currentParagraph ? 'media current' : '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)}
+ >
+ {"["}
+ <MediaCitation media={item} />
+ {"]"}
+ </div>
+ )
+}
diff --git a/animism-align/frontend/app/views/viewer/transcript/components/index.js b/animism-align/frontend/app/views/viewer/transcript/components/index.js
new file mode 100644
index 0000000..45b7d41
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/transcript/components/index.js
@@ -0,0 +1,22 @@
+import React from 'react'
+
+import {
+ Paragraph, ParagraphHeader
+} from './elementTypes.text'
+
+import {
+ MediaVideo
+} from './elementTypes.video'
+
+import {
+ MediaImage
+} from './elementTypes.image'
+
+export const transcriptElementLookup = {
+ paragraph: React.memo(Paragraph),
+ hidden: React.memo(Paragraph),
+ blockquote: React.memo(Paragraph),
+ header: React.memo(ParagraphHeader),
+ video: React.memo(MediaVideo),
+ image: React.memo(MediaImage),
+}
diff --git a/animism-align/frontend/app/views/viewer/containers/transcript.container.js b/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
index abe0ed1..039e5c8 100644
--- a/animism-align/frontend/app/views/viewer/containers/transcript.container.js
+++ b/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
@@ -4,21 +4,33 @@ import React, { Component } from 'react'
import { connect } from 'react-redux'
import actions from 'app/actions'
-// import * as uploadActions from './upload.actions'
+
+import ParagraphList from 'app/views/paragraph/components/paragraph.list'
+import { transcriptElementLookup } from './components'
+
+const noop = () => {}
class Transcript extends Component {
componentDidMount() {
}
render() {
- const { } = this.props
+ const { viewer } = this.props
return (
- <div className="transcript">
+ <div className={viewer.transcript ? "transcript visible" : "transcript"}>
+ <div className='content'>
+ <ParagraphList
+ paragraphElementLookup={transcriptElementLookup}
+ onAnnotationClick={noop}
+ onParagraphDoubleClick={noop}
+ />
+ </div>
</div>
)
}
}
const mapStateToProps = state => ({
+ viewer: state.viewer,
})
const mapDispatchToProps = dispatch => ({
diff --git a/animism-align/frontend/app/views/viewer/viewer.container.js b/animism-align/frontend/app/views/viewer/viewer.container.js
index ff68c4c..64fc915 100644
--- a/animism-align/frontend/app/views/viewer/viewer.container.js
+++ b/animism-align/frontend/app/views/viewer/viewer.container.js
@@ -8,7 +8,8 @@ import './viewer.css'
import actions from 'app/actions'
import { Loader } from 'app/common'
-import ViewerRouter from './containers/viewer.router'
+import Transcript from './transcript/transcript.container'
+import ViewerRouter from './nav/viewer.router'
class ViewerContainer extends Component {
constructor(props) {
@@ -49,6 +50,7 @@ class ViewerContainer extends Component {
}
return (
<div className='viewer body'>
+ <Transcript />
<Route exact path='/viewer/:component/' component={ViewerRouter} />
</div>
)
@@ -56,7 +58,11 @@ class ViewerContainer extends Component {
}
const mapStateToProps = state => ({
- loaded: !!state.annotation.lookup && !!state.paragraph.lookup && !!state.media.lookup
+ loaded: (
+ !!state.annotation.index.lookup &&
+ !!state.paragraph.index.lookup &&
+ !!state.media.index.lookup
+ )
})
const mapDispatchToProps = dispatch => ({
diff --git a/animism-align/frontend/app/views/viewer/viewer.css b/animism-align/frontend/app/views/viewer/viewer.css
index 00cfa2b..fba83bc 100644
--- a/animism-align/frontend/app/views/viewer/viewer.css
+++ b/animism-align/frontend/app/views/viewer/viewer.css
@@ -1,3 +1,64 @@
.viewer {
background: #fff;
-} \ No newline at end of file
+ color: #000;
+}
+
+/* transcript */
+
+.transcript {
+ width: 100%;
+ height: calc(100% - 3.125rem);
+ overflow: scroll;
+ background: white;
+ color: black;
+ padding: 1rem;
+}
+
+/* general paragraph styles */
+
+.transcript .content {
+ font-family: 'Georgia', serif;
+ width: 100%;
+ padding-bottom: 6rem;
+ position: relative;
+}
+
+.transcript .content > div {
+ margin-bottom: 16px;
+}
+
+/* paragraph subtypes */
+
+.transcript .header {
+ font-size: 32px;
+}
+
+.transcript .paragraph,
+.transcript .hidden {
+ font-size: 16px;
+ line-height: 1.5;
+}
+
+.transcript .blockquote {
+ padding-left: 3rem;
+ line-height: 1.5;
+}
+
+/* sentences */
+
+.transcript span {
+ margin-right: 4px;
+}
+.transcript .media span {
+ margin-right: 0;
+}
+
+.transcript .paragraph .current {
+ box-shadow: -2px -3px 0 #fff,
+ 2px -3px 0 #fff,
+ -2px 3px 0 #fff,
+ 2px 3px 0 #fff;
+ box-decoration-break: clone;
+ background: black;
+ color: white;
+}