template cover with updated example.config.js

This commit is contained in:
Sam Ludford
2019-05-16 10:38:46 +01:00
committed by Lachlan Kermode
parent 6e2ae8cd20
commit db92644624
22 changed files with 12866 additions and 76 deletions

View File

@@ -6,9 +6,31 @@ export default ({ ui, app, methods }) => {
return copy[app.language].legend.default.intro.map(txt => <p>{txt}</p>)
}
function renderHalfWithDot () {
const categories = Object.keys(ui.style.categories).filter(label => label !== 'default')
let firstFill = 'red'
let secondFill = 'yellow'
if (categories.length >= 1) {
firstFill = 'rgb(163, 22, 33)'
}
if (categories.length >= 2) {
secondFill = '#1c5df9'
}
return [
<style>{`.svg-demo { max-width: 30px } .first { fill: ${firstFill} } .second { fill: ${secondFill} } .demo-text { font-size: 9pt; color: white; font-weight:900 }`}</style>,
<svg viewBox='0 0 30 30' className='svg-demo'>
<g className='location demo-element' transform='translate(15,15)'>
<path className="location-event-marker first" id="arc_0" d="M 10 0 A 10 10 0 0 1 -10 1.2246467991473533e-15 L 0 0 L 10 0 Z" />
<path class="location-event-marker second" id="arc_1" d="M -10 1.2246467991473533e-15 A 10 10 0 0 1 10 -2.4492935982947065e-15 L 0 0 L -10 1.2246467991473533e-15 Z" />
<text class="location-count demo-text" dx="-4" dy="4">2</text>
</g>
</svg>
]
}
function renderCategoryColors () {
const categories = Object.keys(ui.style.categories).filter(label => label !== 'default')
categories.reverse()
return categories.map(category => (
<div className='legend-section'>
<svg x='0px' y='0px' width='50px' height='20px' viewBox='0 0 100 30' enableBackground='new 0 0 100 30'>
@@ -21,7 +43,21 @@ export default ({ ui, app, methods }) => {
))
}
function renderArrow (strokeFill) {
return (
<svg x='-10px' y='0px' width='100px' height='30px' viewBox='0 40 100 30' enableBackground='new 0 0 100 70'>
<polyline fill='none' stroke={strokeFill} strokeWidth='2' strokeLinecap='round' strokeLinejoin='round' stroke-miterlimit='10' points='
8.376,63.723 47.287,63.723 60,46 80,46 ' />
{/* <line stroke={strokeFill} strokeWidth='2' strokeLinecap='round' strokeLinejoin='round' x1='33.723' y1='59.663' x2='39.069' y2='63.723' /> */}
{/* <line stroke={strokeFill} strokeWidth='2' strokeLinecap='round' strokeLinejoin='round' x1='33.723' y1='67.782' x2='39.069' y2='63.723' /> */}
<line stroke={strokeFill} strokeWidth='2' strokeLinecap='round' strokeLinejoin='round' x1='78.849' y1='41.94' x2='84.195' y2='46' />
<line stroke={strokeFill} strokeWidth='2' strokeLinecap='round' strokeLinejoin='round' x1='78.849' y1='50.06' x2='84.195' y2='46' />
</svg>
)
}
function renderView2DLegend () {
const categories = Object.keys(ui.style.categories).filter(label => label !== 'default')
return (
<div className={`infopopup ${(app.flags.isInfopopup) ? '' : 'hidden'}`}>
<div className='legend-header'>
@@ -29,11 +65,39 @@ export default ({ ui, app, methods }) => {
<h2>{copy[app.language].legend.default.header}</h2>
</div>
{renderIntro()}
<div>
{renderCategoryColors()}
</div>
<br />
<div className='legend'>
<div className='legend-container'>
{renderCategoryColors()}
<div className='legend-item one'>
{renderHalfWithDot()}
</div>
<div className='legend-item three'>
{copy[app.language].legend.default.notation}
</div>
</div>
</div>
<br/>
<div>
<p>In narratives, arrows indicate physical movement between two events.</p>
</div>
{
ui.style.arrows ? (
Object.keys(ui.style.arrows).map( arrowName => (
<div className='legend-section'>
{renderArrow(ui.style.arrows[arrowName])}
<div className='legend-labels'>
<div className='label'>{arrowName}</div>
</div>
</div>
))
) : null
}
</div>
)
}

View File

@@ -14,7 +14,7 @@ import InfoPopUp from './InfoPopup.jsx'
import Timeline from './Timeline.jsx'
import Notification from './Notification.jsx'
import StaticPage from './StaticPage'
import DefaultCover from './presentational/covers/Default'
import TemplateCover from './presentational/covers/TemplateCover'
import { parseDate } from '../js/utilities'
@@ -108,7 +108,7 @@ class Dashboard extends React.Component {
<StaticPage showing={app.flags.isCover}>
{/* enable USE_COVER in config.js features, and customise your header */}
{/* pass 'actions.toggleCover' as a prop to your custom header */}
<DefaultCover showAppHandler={() => {
<TemplateCover showAppHandler={() => {
/* eslint-disable no-undef */
alert('This platform is not suitable for mobile. Please re-visit the site on a device with a larger screen.')
/* eslint-enable no-undef */
@@ -187,7 +187,7 @@ class Dashboard extends React.Component {
<StaticPage showing={app.flags.isCover}>
{/* enable USE_COVER in config.js features, and customise your header */}
{/* pass 'actions.toggleCover' as a prop to your custom header */}
<DefaultCover showAppHandler={actions.toggleCover} />
<TemplateCover showing={app.flags.isCover} showAppHandler={actions.toggleCover} />
</StaticPage>
)}
<LoadingOverlay

View File

@@ -17,6 +17,7 @@ import DefsMarkers from './presentational/Map/DefsMarkers.jsx'
// NB: important constants for map, TODO: make statics
const supportedMapboxMap = ['streets', 'satellite']
const defaultToken = 'your_token'
class Map extends React.Component {
constructor () {
@@ -69,17 +70,14 @@ class Map extends React.Component {
let firstLayer
// if mapbox token and one of the default maps are specified
if ((supportedMapboxMap.indexOf(this.props.ui.tiles) !== -1) && process.env.MAPBOX_TOKEN) {
if ((supportedMapboxMap.indexOf(this.props.ui.tiles) !== -1) && process.env.MAPBOX_TOKEN && process.env.MAPBOX_TOKEN !== defaultToken) {
firstLayer = L.tileLayer(
`http://a.tiles.mapbox.com/v4/mapbox.${this.props.ui.tiles}/{z}/{x}/{y}@2x.png?access_token=${process.env.MAPBOX_TOKEN}`
)
// if mapbox token and custom map
} else if (process.env.MAPBOX_TOKEN) {
} else if (process.env.MAPBOX_TOKEN && process.env.MAPBOX_TOKEN !== defaultToken) {
firstLayer = L.tileLayer(
`http://a.tiles.mapbox.com/styles/v1/${this.props.ui.tiles}/tiles/{z}/{x}/{y}?access_token=${process.env.MAPBOX_TOKEN}`
)
// no mapbox token
} else {
firstLayer = L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'

View File

@@ -10,7 +10,7 @@ export default ({ media, viewIdx }) => {
const shiftW = el ? el.getBoundingClientRect().width : 0
function renderMedia (media) {
const { path, type } = media
const { path, type, poster } = media
switch (type) {
case 'Image':
return (
@@ -27,6 +27,7 @@ export default ({ media, viewIdx }) => {
return (
<div className='media-player'>
<Player
poster={poster}
className='source-video'
playsInline
src={path}

View File

@@ -1,7 +1,7 @@
import React from 'react'
import Content from './Content'
import Controls from './Controls'
import { selectTypeFromPath } from '../../js/utilities'
import { selectTypeFromPathWithPoster } from '../../js/utilities'
class SourceOverlay extends React.Component {
constructor () {
@@ -32,11 +32,11 @@ class SourceOverlay extends React.Component {
if (typeof (this.props.source) !== 'object') {
return this.renderError()
}
const { url, title, paths, date, type } = this.props.source
const { url, title, paths, date, type, desc, poster } = this.props.source
const shortenedTitle = title.substring(0, 100)
return (
<div className='mo-overlay'>
<div className={`mo-overlay ${this.props.opaque ? 'opaque' : ''}`}>
<div className='mo-banner'>
<div className='mo-banner-close' onClick={this.props.onCancel}>
<i className='material-icons'>close</i>
@@ -49,7 +49,7 @@ class SourceOverlay extends React.Component {
<div className='mo-container' onClick={e => e.stopPropagation()}>
<div className='mo-media-container'>
<Content media={paths.map(selectTypeFromPath)} viewIdx={this.state.idx} />
<Content media={paths.map(p => selectTypeFromPathWithPoster(p, poster))} viewIdx={this.state.idx} />
</div>
</div>
@@ -58,25 +58,24 @@ class SourceOverlay extends React.Component {
<Controls paths={paths} viewIdx={this.state.idx} onShiftHandler={this.onShiftGallery} />
<div className='mo-meta-container'>
{/* <div className='mo-box-title'> */}
{/* {title ? <p><b>{title}</b></p> : null} */}
{/* <div>{desc}</div> */}
{/* </div> */}
<div className='mo-box-title'>
<div>{desc}</div>
</div>
<div className='mo-box'>
{(type || date || url) ? <div className='mo-box'>
<div>
{type ? <h4>Media type</h4> : null}
{type ? <p><i className='material-icons left'>perm_media</i>{type}</p> : null}
</div>
<div>
{date ? <h4>Date</h4> : null}
{date ? <h4>Date Published</h4> : null}
{date ? <p><i className='material-icons left'>today</i>{date}</p> : null}
</div>
<div>
{url ? <h4>Link</h4> : null}
{url ? <span><i className='material-icons left'>link</i><a href={url} target='_blank'>Link to original URL</a></span> : null}
</div>
</div>
</div> : null}
</div>
</div>

View File

@@ -1,10 +1,9 @@
import React from 'react'
import copy from '../../../js/data/copy.json'
import { isNotNullNorUndefined } from '../../../js/utilities'
const CardLocation = ({ language, location, isPrecise }) => {
if (isNotNullNorUndefined(location)) {
if (location !== '') {
return (
<div className='card-cell location'>
<p>

View File

@@ -96,9 +96,9 @@ function MapEvents ({ getCategoryColor, categories, projectPoint, styleLocation,
return (
<g
className='location'
className={`location ${narrative ? 'no-hover' : ''}`}
transform={`translate(${x}, ${y})`}
onClick={() => onSelect(location.events)}
onClick={(!narrative) ? () => onSelect(location.events) : null}
>
{renderLocationSlicesByCategory(location)}
{extraRender ? extraRender() : null}

View File

@@ -0,0 +1,115 @@
import React from 'react'
import { connect } from "react-redux"
import MediaOverlay from '../../Overlay/Media'
const ReactMarkdown = require('react-markdown')
const MEDIA_HIDDEN = -2
const MEDIA_HOWTO = -1
class TemplateCover extends React.Component {
constructor (props) {
super(props)
this.state = {
video: MEDIA_HIDDEN
}
}
getVideo(index) {
if(index == MEDIA_HOWTO) {
return this.props.cover.howToVideo
} else if(index >= 0) {
return this.props.cover.videos[index]
} else {
return null
}
}
render () {
var video = this.getVideo(this.state.video)
return (
<div className='default-cover-container'>
<div className="cover-content">
{
this.props.cover.bgVideo ? (
<div className={`fullscreen-bg ${!this.props.showing ? 'hidden' : ''}`}>
<video
loop
muted
autoPlay
preload='auto'
className='fullscreen-bg__video'
>
<source src={this.props.cover.bgVideo} type='video/mp4' />
</video>
</div>
) : null
}
<h1 style={{ 'margin-bottom': '-20px', 'text-align': 'center' }}>{this.props.cover.title}</h1>
<h3 style={{ 'text-align': 'center' }}>{this.props.cover.subtitle}</h3>
{
this.props.cover.subsubtitle ? (
<h5 style={{ 'text-align': 'center', 'margin-top': '-10px' }}>{this.props.cover.subsubtitle}</h5>
) : null
}
<hr />
<div className='hero thin'>
{
this.props.cover.howToVideo ? (
<div className='row'>
<div className='cell plain' onClick={() => this.setState({ video: -1 })}>
How to Use the Platform
</div>
</div>
) : null
}
<div className='row'>
<div className='cell yellow' onClick={this.props.showAppHandler}>
EXPLORE
</div>
</div>
</div>
<ReactMarkdown source={this.props.cover.description} />
{
this.props.cover.videos ? (
<div className='hero'>
<div className='row'>
{ this.props.cover.videos.slice(0,4).map( (media, index) => (
<div className='cell small' onClick={() => this.setState({ video: index })} >
{media.buttonTitle}<br />{media.buttonSubtitle}
</div>
)) }
</div>
</div>
) : null
}
</div>
{
this.state.video != MEDIA_HIDDEN ? (
<MediaOverlay
opaque
source={
{
title: video.title,
desc: video.desc,
paths: [video.file],
poster: video.poster
}}
onCancel={() => this.setState({ video: MEDIA_HIDDEN })}
/>
) : null }
</div>
)
}
}
function mapStateToProps(state) {
return {
cover : state.app.cover
}
}
export default connect(mapStateToProps) (TemplateCover);