From 4c7ed7102aa5fdf3245ce1113614fee2d15fbd07 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 24 Jul 2020 19:56:27 +0200 Subject: checklist dropdown --- .../frontend/app/views/site/site.actions.js | 2 +- .../views/viewer/checklist/checklist.container.js | 43 +++++++++--------- .../views/viewer/checklist/checklist.content.js | 30 +++++++++++++ .../app/views/viewer/checklist/checklist.css | 49 +++++++++++++++++++++ .../views/viewer/checklist/checklist.dropdown.js | 51 ++++++++++++++++++++++ .../frontend/app/views/viewer/nav/nav.css | 38 ++++++++++++++-- .../frontend/app/views/viewer/nav/nav.parent.js | 9 ++-- .../frontend/app/views/viewer/nav/viewer.icons.js | 2 + .../app/views/viewer/player/player.container.js | 6 ++- .../frontend/app/views/viewer/viewer.actions.js | 9 ++-- .../frontend/app/views/viewer/viewer.container.js | 4 +- 11 files changed, 204 insertions(+), 39 deletions(-) create mode 100644 animism-align/frontend/app/views/viewer/checklist/checklist.content.js create mode 100644 animism-align/frontend/app/views/viewer/checklist/checklist.dropdown.js (limited to 'animism-align/frontend') diff --git a/animism-align/frontend/app/views/site/site.actions.js b/animism-align/frontend/app/views/site/site.actions.js index b200f32..ee6c523 100644 --- a/animism-align/frontend/app/views/site/site.actions.js +++ b/animism-align/frontend/app/views/site/site.actions.js @@ -12,7 +12,7 @@ export const loadProject = () => dispatch => { ]).then(() => { actions.viewer.loadSections() }).catch(err => { - // console.error(err) + console.error(err) }) } diff --git a/animism-align/frontend/app/views/viewer/checklist/checklist.container.js b/animism-align/frontend/app/views/viewer/checklist/checklist.container.js index da4d6c3..3a441fa 100644 --- a/animism-align/frontend/app/views/viewer/checklist/checklist.container.js +++ b/animism-align/frontend/app/views/viewer/checklist/checklist.container.js @@ -1,36 +1,35 @@ import React, { Component } from 'react' -// import { Link } from 'react-router-dom' -// import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' import actions from 'app/actions' -// import * as uploadActions from './upload.actions' + +import ChecklistDropdown from './checklist.dropdown' +import ChecklistContent from './checklist.content' class Checklist extends Component { - componentDidMount() { + state = { + currentSection: 'all', + } + constructor(props) { + super(props) + this.handleSectionChange = this.handleSectionChange.bind(this) + } + handleSectionChange(currentSection) { + this.setState({ currentSection }) } render() { - const { } = this.props + const { currentSection } = this.state return (
-
-
-
-
-
-
-
-
+ +
) } } -const mapStateToProps = state => ({ -}) - -const mapDispatchToProps = dispatch => ({ - // uploadActions: bindActionCreators({ ...uploadActions }, dispatch), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(Checklist) +export default Checklist diff --git a/animism-align/frontend/app/views/viewer/checklist/checklist.content.js b/animism-align/frontend/app/views/viewer/checklist/checklist.content.js new file mode 100644 index 0000000..ae72adf --- /dev/null +++ b/animism-align/frontend/app/views/viewer/checklist/checklist.content.js @@ -0,0 +1,30 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' + +import actions from 'app/actions' + +class ChecklistContent extends Component { + render() { + const { sections, currentSection } = this.props + return ( +
+
+
+ {sections.map(section => { + if (currentSection !== "all" || section.index !== currentSection) return + return ( +
+ ) + })} +
+
+
+ ) + } +} + +const mapStateToProps = state => ({ + sections: state.viewer.sections, +}) + +export default connect(mapStateToProps)(ChecklistContent) diff --git a/animism-align/frontend/app/views/viewer/checklist/checklist.css b/animism-align/frontend/app/views/viewer/checklist/checklist.css index b6ea6f1..4e87335 100644 --- a/animism-align/frontend/app/views/viewer/checklist/checklist.css +++ b/animism-align/frontend/app/views/viewer/checklist/checklist.css @@ -9,7 +9,56 @@ transition: transform 0.2s; background: white; color: black; + font-size: 16px; + padding: 1.5rem; } .checklist-open .checklist { transform: translateZ(0) translateY(0); } + + +/* dropdown */ + +.checklist-dropdown-container { + width: 12rem; + cursor: pointer; +} +.checklist-dropdown { + display: flex; + flex-flow: row nowrap; + justify-content: space-between; + align-items: center; + border: 1px solid black; + padding-left: 0.5rem; +} +.checklist-dropdown .arrow-box { + display: flex; + justify-content: center; + align-items: center; + padding: 0 0.5rem; + border-left: 1px solid black; +} +.checklist-dropdown .arrow { + width: 2.5rem; + height: 2rem; +} +.checklist-dropdown-options { + border-left: 1px solid black; + border-right: 1px solid black; + border-bottom: 1px solid black; + transition: height 0.2s; + overflow: hidden; + position: relative; + top: -1px; +} +.checklist-dropdown-options.open { + top: 0; +} +.checklist-dropdown-options div { + padding: 0.25rem 0.5rem; + transition: all 0.1s; +} +.checklist-dropdown-options div:hover { + color: white; + background: black; +} diff --git a/animism-align/frontend/app/views/viewer/checklist/checklist.dropdown.js b/animism-align/frontend/app/views/viewer/checklist/checklist.dropdown.js new file mode 100644 index 0000000..0ed2f0d --- /dev/null +++ b/animism-align/frontend/app/views/viewer/checklist/checklist.dropdown.js @@ -0,0 +1,51 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' + +import actions from 'app/actions' +import { ROMAN_NUMERALS } from 'app/constants' +import { Arrow } from '../nav/viewer.icons' + +class ChecklistDropdown extends Component { + state = { + open: false, + } + handleOpen() { + this.setState({ open: !this.state.open }) + } + handleSelect(index) { + this.props.onChange(index) + this.setState({ open: false }) + } + render() { + const { sections, currentSection } = this.props + const { open } = this.state + return ( +
+
+
this.handleOpen()}> + {currentSection === 'all' ? 'View All' : 'Section ' + ROMAN_NUMERALS[currentSection]} +
+ +
+
+
+ {sections.map(section => ( +
this.handleSelect(section.index)}> + {'Section '}{ROMAN_NUMERALS[section.index]} +
+ ))} +
+
+
+ ) + } +} + +const mapStateToProps = state => ({ + sections: state.viewer.sections, +}) + +export default connect(mapStateToProps)(ChecklistDropdown) diff --git a/animism-align/frontend/app/views/viewer/nav/nav.css b/animism-align/frontend/app/views/viewer/nav/nav.css index 69afa29..a6c74d5 100644 --- a/animism-align/frontend/app/views/viewer/nav/nav.css +++ b/animism-align/frontend/app/views/viewer/nav/nav.css @@ -11,6 +11,11 @@ transform: translateZ(0) translateY(0); border-top: 1px solid transparent; } +.main-nav:hover { + background: black; + color: white; +} + .nav-open .main-nav { transform: translateZ(0) translateY(-22rem); border-top: 1px solid #fff; @@ -57,9 +62,16 @@ display: flex; flex-direction: row; justify-content: center; + max-width: 100%; + white-space: nowrap; align-items: center; cursor: pointer; } +.viewer-nav .link span { + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; +} .transcript-link { padding-right: 1.25rem; @@ -67,6 +79,11 @@ /* Arrows */ +.arrow svg { + width: 100%; + height: 100%; +} + .viewer-nav .arrow { display: inline-block; width: 2.5rem; @@ -87,10 +104,10 @@ .viewer-nav .arrow polygon { fill: #000; } +.viewer-nav .main-nav:hover .arrow path, +.viewer-nav .main-nav:hover .arrow polygon, .nav-open .viewer-nav .arrow path, -.nav-open .viewer-nav .arrow polygon { - fill: #fff; -} +.nav-open .viewer-nav .arrow polygon, .checklist-open .viewer-nav .arrow path, .checklist-open .viewer-nav .arrow polygon { fill: #fff; @@ -125,9 +142,11 @@ stroke: #000; stroke-width: 0.5; } +.main-nav:hover .volume path, .nav-open .volume path { fill: #fff; } +.main-nav:hover .volume.muted path, .nav-open .volume.muted path { fill: #000; stroke: #fff; @@ -144,6 +163,8 @@ .playToggle polygon { fill: #000; } +.main-nav:hover .playToggle path, +.main-nav:hover .playToggle polygon, .nav-open .playToggle path, .nav-open .playToggle polygon { fill: #fff; @@ -154,4 +175,15 @@ .playerTime { margin-left: 0.5rem; margin-right: 0.75rem; + cursor: default; +} +@media only screen and (max-width: 950px) { + .playerDuration { + display: none; + } +} +@media only screen and (max-width: 1200px) { + .transcript-open .playerDuration { + display: none; + } } 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 f932648..62830bc 100644 --- a/animism-align/frontend/app/views/viewer/nav/nav.parent.js +++ b/animism-align/frontend/app/views/viewer/nav/nav.parent.js @@ -1,5 +1,4 @@ import React, { Component } from 'react' -// import { Link } from 'react-router-dom' import { connect } from 'react-redux' import actions from 'app/actions' @@ -16,9 +15,11 @@ class NavParent extends Component {
actions.viewer.toggleSection('nav')}> - {ROMAN_NUMERALS[0]} - {'. '} - {'Introduction'} + + {ROMAN_NUMERALS[0]} + {'. '} + {'Introduction'} +
diff --git a/animism-align/frontend/app/views/viewer/nav/viewer.icons.js b/animism-align/frontend/app/views/viewer/nav/viewer.icons.js index a39cb16..da3ecbf 100644 --- a/animism-align/frontend/app/views/viewer/nav/viewer.icons.js +++ b/animism-align/frontend/app/views/viewer/nav/viewer.icons.js @@ -76,7 +76,9 @@ export const PlayButton = ({ playing }) => { export const PlayerTime = ({ play_ts, duration }) => ( {timestamp(play_ts)} + {' / '} {timestamp(duration)} + ) 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 0ad1bab..aefc025 100644 --- a/animism-align/frontend/app/views/viewer/player/player.container.js +++ b/animism-align/frontend/app/views/viewer/player/player.container.js @@ -11,8 +11,10 @@ class PlayerContainer extends Component { render() { const { } = this.props return ( -
- Document container +
+
+ Document container +
) } diff --git a/animism-align/frontend/app/views/viewer/viewer.actions.js b/animism-align/frontend/app/views/viewer/viewer.actions.js index 3d69b1f..aa5124f 100644 --- a/animism-align/frontend/app/views/viewer/viewer.actions.js +++ b/animism-align/frontend/app/views/viewer/viewer.actions.js @@ -2,30 +2,31 @@ import * as types from 'app/types' import { store, history, dispatch } from 'app/store' import { MEDIA_TYPES } from 'app/constants' -const newSection = (annotation, index) => ({ +const newSection = (annotation, index, mediaIndex) => ({ start_ts: annotation.start_ts, title: annotation.text, media: [], index, + mediaIndex, }) export const loadSections = () => dispatch => { - let sections = [], currentSection + let sections = [], currentSection, mediaIndex = 0 const state = store.getState() const { order: annotationOrder, lookup: annotationLookup } = state.annotation.index const { lookup: mediaLookup } = state.media.index - // loop over the annotations in time order. group the media found in each section. annotationOrder.forEach((annotation_id, i) => { const annotation = annotationLookup[annotation_id] if (annotation.type === 'header') { - currentSection = newSection(annotation, sections.length) + currentSection = newSection(annotation, sections.length, mediaIndex) sections.push(currentSection) } if (MEDIA_TYPES.has(annotation.type)) { if (currentSection) { const media = mediaLookup[annotation.settings.media_id] currentSection.media.push(media) + mediaIndex += 1 } else { console.error("media found before first section") } diff --git a/animism-align/frontend/app/views/viewer/viewer.container.js b/animism-align/frontend/app/views/viewer/viewer.container.js index 5949c37..6f476fc 100644 --- a/animism-align/frontend/app/views/viewer/viewer.container.js +++ b/animism-align/frontend/app/views/viewer/viewer.container.js @@ -72,9 +72,7 @@ class ViewerContainer extends Component {
-
- -
+ -- cgit v1.2.3-70-g09d2