summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/app')
-rw-r--r--animism-align/frontend/app/types.js2
-rw-r--r--animism-align/frontend/app/views/viewer/checklist/checklist.content.js4
-rw-r--r--animism-align/frontend/app/views/viewer/nav/nav.parent.js2
-rw-r--r--animism-align/frontend/app/views/viewer/nav/viewer.router.js6
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js46
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.text.js37
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.video.js21
-rw-r--r--animism-align/frontend/app/views/viewer/player/components.inline/index.js24
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.container.css18
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.container.js19
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.css4
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.fullscreen.css14
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.fullscreen.js22
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.transcript.css4
-rw-r--r--animism-align/frontend/app/views/viewer/player/player.transcript.js1
-rw-r--r--animism-align/frontend/app/views/viewer/sections/viewer.sections.js2
-rw-r--r--animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js6
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js1
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js1
-rw-r--r--animism-align/frontend/app/views/viewer/transcript/transcript.container.js3
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.actions.js16
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.container.js2
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.css14
-rw-r--r--animism-align/frontend/app/views/viewer/viewer.reducer.js11
24 files changed, 230 insertions, 50 deletions
diff --git a/animism-align/frontend/app/types.js b/animism-align/frontend/app/types.js
index 4ccf483..8418bb5 100644
--- a/animism-align/frontend/app/types.js
+++ b/animism-align/frontend/app/types.js
@@ -25,7 +25,7 @@ export const audio = with_type('audio', [
])
export const viewer = with_type('viewer', [
- 'load_sections', 'toggle_section'
+ 'load_sections', 'toggle_component', 'set_current_section',
])
export const site = with_type('site', [
diff --git a/animism-align/frontend/app/views/viewer/checklist/checklist.content.js b/animism-align/frontend/app/views/viewer/checklist/checklist.content.js
index e4e47ec..dfccb61 100644
--- a/animism-align/frontend/app/views/viewer/checklist/checklist.content.js
+++ b/animism-align/frontend/app/views/viewer/checklist/checklist.content.js
@@ -10,8 +10,8 @@ import { PlayIcon } from '../nav/viewer.icons'
class ChecklistContent extends Component {
handleMediaSelection(mediaItem) {
actions.audio.seek(mediaItem.start_ts)
- actions.viewer.hideSection('nav')
- actions.viewer.hideSection('checklist')
+ actions.viewer.hideComponent('nav')
+ actions.viewer.hideComponent('checklist')
}
render() {
const { sections, currentSection } = this.props
diff --git a/animism-align/frontend/app/views/viewer/nav/nav.parent.js b/animism-align/frontend/app/views/viewer/nav/nav.parent.js
index 62830bc..fb505c2 100644
--- a/animism-align/frontend/app/views/viewer/nav/nav.parent.js
+++ b/animism-align/frontend/app/views/viewer/nav/nav.parent.js
@@ -13,7 +13,7 @@ class NavParent extends Component {
<div className="viewer-nav">
<div className='nav-row main-nav'>
<div className='nav-section-name'>
- <span className="section-link link" onClick={() => actions.viewer.toggleSection('nav')}>
+ <span className="section-link link" onClick={() => actions.viewer.toggleComponent('nav')}>
<Arrow type={viewer.nav ? 'down' : 'up'} />
<span>
{ROMAN_NUMERALS[0]}
diff --git a/animism-align/frontend/app/views/viewer/nav/viewer.router.js b/animism-align/frontend/app/views/viewer/nav/viewer.router.js
index e352af5..75aaed7 100644
--- a/animism-align/frontend/app/views/viewer/nav/viewer.router.js
+++ b/animism-align/frontend/app/views/viewer/nav/viewer.router.js
@@ -12,13 +12,13 @@ class ViewerRouter extends Component {
// console.log(this.props.match.params.component)
switch (this.props.match.params.component) {
case 'transcript':
- actions.viewer.showSection('transcript')
+ actions.viewer.showComponent('transcript')
break
case 'nav':
- actions.viewer.showSection('nav')
+ actions.viewer.showComponent('nav')
break
case 'checklist':
- actions.viewer.showSection('checklist')
+ actions.viewer.showComponent('checklist')
break
case 'fullscreenImage':
break
diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js
new file mode 100644
index 0000000..f005fc0
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js
@@ -0,0 +1,46 @@
+import React, { Component } from 'react'
+
+export const MediaCitation = ({ media }) => {
+ if (media.citation) {
+ return (
+ <span dangerouslySetInnerHTML={{ _html: media.citation }} />
+ )
+ }
+ 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/player/components.inline/elementTypes.text.js b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.text.js
new file mode 100644
index 0000000..8825479
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.text.js
@@ -0,0 +1,37 @@
+import React, { Component } from 'react'
+
+import { ROMAN_NUMERALS } from 'app/constants'
+
+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 ParagraphHeading = ({ 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)}
+ >
+ <span>{ROMAN_NUMERALS[paragraph.sectionIndex]}{'. '}{text}</span>
+ </div>
+ )
+}
diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.video.js b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.video.js
new file mode 100644
index 0000000..fe821eb
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/player/components.inline/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/player/components.inline/index.js b/animism-align/frontend/app/views/viewer/player/components.inline/index.js
new file mode 100644
index 0000000..ee65641
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/player/components.inline/index.js
@@ -0,0 +1,24 @@
+import React from 'react'
+
+import {
+ Paragraph, ParagraphHeading
+} 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),
+ section_heading: React.memo(ParagraphHeading),
+ heading_text: React.memo(ParagraphHeading),
+ header: React.memo(ParagraphHeading),
+ video: React.memo(MediaVideo),
+ image: React.memo(MediaImage),
+}
diff --git a/animism-align/frontend/app/views/viewer/player/player.container.css b/animism-align/frontend/app/views/viewer/player/player.container.css
new file mode 100644
index 0000000..4a0d539
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/player/player.container.css
@@ -0,0 +1,18 @@
+.viewer-container {
+ position: absolute;
+ top: 0; left: 0;
+ width: 100vw;
+ height: 100vh;
+ /*transform: translateZ(0) translateX(0);*/
+ transition: all 0.2s;
+}
+
+.transcript-open .viewer-container {
+ /*transform: translateZ(0) translateX(-31.875rem);*/
+ width: calc(100vw - 31.875rem);
+}
+
+.nav-open .viewer-container {
+ /*transform: translateZ(0) translateX(-31.875rem);*/
+ height: calc(100vh - 25rem);
+}
diff --git a/animism-align/frontend/app/views/viewer/player/player.container.js b/animism-align/frontend/app/views/viewer/player/player.container.js
index 0340171..1ddb5c7 100644
--- a/animism-align/frontend/app/views/viewer/player/player.container.js
+++ b/animism-align/frontend/app/views/viewer/player/player.container.js
@@ -1,20 +1,16 @@
import React, { Component } from 'react'
-// import { Link } from 'react-router-dom'
import { connect } from 'react-redux'
import { floatInRange } from 'app/utils'
import actions from 'app/actions'
import PlayerTranscript from './player.transcript'
+import PlayerFullscreen from './player.fullscreen'
class PlayerContainer extends Component {
- state = {
- currentSection: null,
- }
-
componentDidMount() {
// console.log(this.props.sections)
- this.setState({ currentSection: this.props.sections[0] })
+ actions.viewer.setCurrentSection(this.props.sections[0])
}
componentDidUpdate(prevProps) {
@@ -23,8 +19,7 @@ class PlayerContainer extends Component {
}
setCurrentSection() {
- const { currentSection } = this.state
- const { audio, sections } = this.props
+ const { audio, sections, currentSection } = this.props
const { play_ts } = audio
if (floatInRange(currentSection.start_ts, play_ts, currentSection.end_ts)) {
return
@@ -33,26 +28,27 @@ class PlayerContainer extends Component {
const insideSection = sections.some(section => {
if (floatInRange(section.start_ts, play_ts, section.end_ts)) {
if (currentSection !== section) {
- this.setState({ currentSection: section })
+ actions.viewer.setCurrentSection(section)
}
return true
}
return false
})
if (!insideSection) {
- this.setState({ currentSection: sections[0] })
+ actions.viewer.setCurrentSection(sections[0])
}
}
render() {
// const { } = this.props
- const { currentSection } = this.state
+ const { currentSection, fullscreenTimeline } = this.props
if (!currentSection) { return <div /> }
// console.log(currentSection)
return (
<div className='viewer-container'>
<PlayerTranscript section={currentSection} />
+ <PlayerFullscreen timeline={fullscreenTimeline} />
</div>
)
}
@@ -62,6 +58,7 @@ const mapStateToProps = state => ({
audio: state.audio,
sections: state.viewer.sections,
fullscreenTimeline: state.viewer.fullscreenTimeline,
+ currentSection: state.viewer.currentSection,
})
export default connect(mapStateToProps)(PlayerContainer)
diff --git a/animism-align/frontend/app/views/viewer/player/player.css b/animism-align/frontend/app/views/viewer/player/player.css
deleted file mode 100644
index 76a78eb..0000000
--- a/animism-align/frontend/app/views/viewer/player/player.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.viewer-container {
- position: absolute;
- top: 0; left: 0;
-} \ No newline at end of file
diff --git a/animism-align/frontend/app/views/viewer/player/player.fullscreen.css b/animism-align/frontend/app/views/viewer/player/player.fullscreen.css
new file mode 100644
index 0000000..8041c84
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/player/player.fullscreen.css
@@ -0,0 +1,14 @@
+.viewer-fullscreen {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ pointer-events: none;
+ user-select: none;
+}
+.viewer-fullscreen.active {
+ pointer-events: auto;
+ user-select: auto;
+} \ No newline at end of file
diff --git a/animism-align/frontend/app/views/viewer/player/player.fullscreen.js b/animism-align/frontend/app/views/viewer/player/player.fullscreen.js
new file mode 100644
index 0000000..89052ed
--- /dev/null
+++ b/animism-align/frontend/app/views/viewer/player/player.fullscreen.js
@@ -0,0 +1,22 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+
+import actions from 'app/actions'
+
+class PlayerFullscreen extends Component {
+ componentDidMount() {
+ }
+
+ render() {
+ const { } = this.props
+ return (
+ <div className="viewer-fullscreen">
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+})
+
+export default connect(mapStateToProps)(PlayerFullscreen)
diff --git a/animism-align/frontend/app/views/viewer/player/player.transcript.css b/animism-align/frontend/app/views/viewer/player/player.transcript.css
index f9a9863..4ca9475 100644
--- a/animism-align/frontend/app/views/viewer/player/player.transcript.css
+++ b/animism-align/frontend/app/views/viewer/player/player.transcript.css
@@ -60,6 +60,10 @@
.player-transcript .hidden {
}
+.player-transcript .paragraph:last-child {
+ margin-bottom: 6rem;
+}
+
.player-transcript .blockquote {
padding-left: 2rem;
line-height: 1.45;
diff --git a/animism-align/frontend/app/views/viewer/player/player.transcript.js b/animism-align/frontend/app/views/viewer/player/player.transcript.js
index a315781..530b9d6 100644
--- a/animism-align/frontend/app/views/viewer/player/player.transcript.js
+++ b/animism-align/frontend/app/views/viewer/player/player.transcript.js
@@ -22,7 +22,6 @@ class PlayerTranscript extends Component {
}
handleParagraphDoubleClick(e, paragraph) {
- return
}
handleClose() {
diff --git a/animism-align/frontend/app/views/viewer/sections/viewer.sections.js b/animism-align/frontend/app/views/viewer/sections/viewer.sections.js
index 085749f..b9d29a1 100644
--- a/animism-align/frontend/app/views/viewer/sections/viewer.sections.js
+++ b/animism-align/frontend/app/views/viewer/sections/viewer.sections.js
@@ -13,7 +13,7 @@ class ViewerSections extends Component {
handleSectionSelection(section) {
actions.audio.seek(section.start_ts)
- actions.viewer.hideSection('nav')
+ actions.viewer.hideComponent('nav')
}
render() {
diff --git a/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js b/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js
index 439b905..19eb385 100644
--- a/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js
+++ b/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js
@@ -18,15 +18,15 @@ class ViewerSectionsNav extends Component {
</span>
</div>
<div>
- <span className="checklist-link link" onClick={() => actions.viewer.toggleSection('checklist')}>
+ <span className="checklist-link link" onClick={() => actions.viewer.toggleComponent('checklist')}>
<Arrow type={viewer.checklist ? 'down': 'up'} />
{'Checklist'}
</span>
</div>
<div>
<span className="transcript-link link" onClick={() => {
- actions.viewer.hideSection('checklist')
- actions.viewer.toggleSection('transcript')
+ actions.viewer.hideComponent('checklist')
+ actions.viewer.toggleComponent('transcript')
}}>
{'Transcript'}
</span>
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
index f005fc0..9269461 100644
--- a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js
+++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.image.js
@@ -36,6 +36,7 @@ export const MediaImage = ({ paragraph, media, currentParagraph, currentAnnotati
return (
<div
className={className}
+ onClick={e => onAnnotationClick(e, paragraph, annotation)}
onDoubleClick={e => onDoubleClick(e, paragraph)}
>
{"["}
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
index fe821eb..6c2a05b 100644
--- a/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js
+++ b/animism-align/frontend/app/views/viewer/transcript/components/elementTypes.video.js
@@ -11,6 +11,7 @@ export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotati
return (
<div
className={className}
+ onClick={e => onAnnotationClick(e, paragraph, annotation)}
onDoubleClick={e => onDoubleClick(e, paragraph)}
>
{"["}
diff --git a/animism-align/frontend/app/views/viewer/transcript/transcript.container.js b/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
index afd2fd1..c0ce242 100644
--- a/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
+++ b/animism-align/frontend/app/views/viewer/transcript/transcript.container.js
@@ -22,6 +22,7 @@ class Transcript extends Component {
handleAnnotationClick(e, paragraph, annotation) {
console.log(annotation)
+ actions.audio.seek(annotation.start_ts)
}
handleParagraphDoubleClick(e, paragraph) {
@@ -29,7 +30,7 @@ class Transcript extends Component {
}
handleClose() {
- actions.viewer.hideSection('transcript')
+ actions.viewer.hideComponent('transcript')
}
render() {
diff --git a/animism-align/frontend/app/views/viewer/viewer.actions.js b/animism-align/frontend/app/views/viewer/viewer.actions.js
index cb5c119..40a4718 100644
--- a/animism-align/frontend/app/views/viewer/viewer.actions.js
+++ b/animism-align/frontend/app/views/viewer/viewer.actions.js
@@ -134,14 +134,18 @@ const makeFullscreenEvent = annotation => {
return event
}
-export const showSection = section => dispatch => {
- dispatch({ type: types.viewer.toggle_section, key: section, value: true })
+export const setCurrentSection = section => dispatch => {
+ dispatch({ type: types.viewer.set_current_section, section })
}
-export const hideSection = section => dispatch => {
- dispatch({ type: types.viewer.toggle_section, key: section, value: false })
+export const showComponent = key => dispatch => {
+ dispatch({ type: types.viewer.toggle_component, key, value: true })
}
-export const toggleSection = section => dispatch => {
- dispatch({ type: types.viewer.toggle_section, key: section, value: !store.getState().viewer[section] })
+export const hideComponent = key => dispatch => {
+ dispatch({ type: types.viewer.toggle_component, key, value: false })
+}
+
+export const toggleComponent = key => dispatch => {
+ dispatch({ type: types.viewer.toggle_component, key, value: !store.getState().viewer[key] })
}
diff --git a/animism-align/frontend/app/views/viewer/viewer.container.js b/animism-align/frontend/app/views/viewer/viewer.container.js
index 5bf190e..66e9e3d 100644
--- a/animism-align/frontend/app/views/viewer/viewer.container.js
+++ b/animism-align/frontend/app/views/viewer/viewer.container.js
@@ -10,6 +10,8 @@ import './nav/eflux.css'
import './sections/sections.css'
import './transcript/transcript.css'
import './checklist/checklist.css'
+import './player/player.container.css'
+import './player/player.fullscreen.css'
import './player/player.transcript.css'
import actions from 'app/actions'
diff --git a/animism-align/frontend/app/views/viewer/viewer.css b/animism-align/frontend/app/views/viewer/viewer.css
index d0f7177..b0df181 100644
--- a/animism-align/frontend/app/views/viewer/viewer.css
+++ b/animism-align/frontend/app/views/viewer/viewer.css
@@ -30,17 +30,3 @@
background-repeat: no-repeat;
cursor: pointer;
}
-
-.viewer-container {
- position: absolute;
- top: 0; left: 0;
- width: 100vw;
- height: 100vh;
- /*transform: translateZ(0) translateX(0);*/
- transition: width 0.2s;
-}
-
-.transcript-open .viewer-container {
- /*transform: translateZ(0) translateX(-31.875rem);*/
- width: calc(100vw - 31.875rem);
-}
diff --git a/animism-align/frontend/app/views/viewer/viewer.reducer.js b/animism-align/frontend/app/views/viewer/viewer.reducer.js
index 9eda4b5..73a961f 100644
--- a/animism-align/frontend/app/views/viewer/viewer.reducer.js
+++ b/animism-align/frontend/app/views/viewer/viewer.reducer.js
@@ -6,6 +6,7 @@ const initialState = {
nav: false,
sections: { loading: true },
fullscreenTimeline: [],
+ currentSection: null,
options: {
}
}
@@ -13,6 +14,12 @@ const initialState = {
export default function viewerReducer(state = initialState, action) {
// console.log(action.type, action)
switch (action.type) {
+ case types.viewer.toggle_component:
+ return {
+ ...state,
+ [action.key]: action.value,
+ }
+
case types.viewer.load_sections:
return {
...state,
@@ -20,10 +27,10 @@ export default function viewerReducer(state = initialState, action) {
fullscreenTimeline: action.fullscreenTimeline,
}
- case types.viewer.toggle_section:
+ case types.viewer.set_current_section:
return {
...state,
- [action.key]: action.value,
+ currentSection: action.section,
}
default: