significantly refactor presentational components

This commit is contained in:
Lachlan Kermode
2019-01-18 11:51:00 +00:00
parent f561064e6c
commit e7cac13fb5
34 changed files with 103 additions and 150 deletions

BIN
src/components/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -7,14 +7,14 @@ import {
import React from 'react'
import Spinner from './presentational/Spinner'
import CardTimestamp from './presentational/CardTimestamp'
import CardLocation from './presentational/CardLocation'
import CardCaret from './presentational/CardCaret'
import CardTags from './presentational/CardTags'
import CardSummary from './presentational/CardSummary'
import CardSource from './presentational/CardSource'
import CardCategory from './presentational/CardCategory'
import CardNarrative from './presentational/CardNarrative'
import CardTimestamp from './presentational/Card/Timestamp'
import CardLocation from './presentational/Card/Location'
import CardCaret from './presentational/Card/Caret'
import CardTags from './presentational/Card/Tags'
import CardSummary from './presentational/Card/Summary'
import CardSource from './presentational/Card/Source'
import CardCategory from './presentational/Card/Category'
import CardNarrative from './presentational/Card/Narrative'
class Card extends React.Component {

View File

@@ -9,7 +9,7 @@ import LoadingOverlay from './presentational/LoadingOverlay'
import Map from './Map.jsx'
import Toolbar from './Toolbar.jsx'
import CardStack from './CardStack.jsx'
import NarrativeControls from './presentational/NarrativeControls.js'
import NarrativeControls from './presentational/Narrative/Controls.js'
import InfoPopUp from './InfoPopup.jsx'
import Timeline from './Timeline.jsx'
import Notification from './Notification.jsx'

View File

@@ -9,17 +9,18 @@ import 'leaflet';
import { isNotNullNorUndefined } from '../js/utilities';
import MapSites from './MapSites.jsx';
import MapShapes from './MapShapes.jsx';
import MapEvents from './MapEvents.jsx';
import MapSelectedEvents from './MapSelectedEvents.jsx';
import MapNarratives from './MapNarratives.jsx';
import MapDefsMarkers from './MapDefsMarkers.jsx';
import MapSites from './presentational/Map/Sites.jsx';
import MapShapes from './presentational/Map/Shapes.jsx';
import MapEvents from './presentational/Map/Events.jsx';
import MapSelectedEvents from './presentational/Map/SelectedEvents.jsx';
import MapNarratives from './presentational/Map/Narratives.jsx';
import MapDefsMarkers from './presentational/Map/DefsMarkers.jsx';
class Map extends React.Component {
constructor() {
super();
this.projectPoint = this.projectPoint.bind(this)
this.svgRef = React.createRef();
this.map = null;
this.state = {
@@ -109,6 +110,14 @@ class Map extends React.Component {
})
}
projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1])
return {
x: this.map.latLngToLayerPoint(latLng).x + this.state.mapTransformX,
y: this.map.latLngToLayerPoint(latLng).y + this.state.mapTransformY
}
}
getClientDims() {
const boundingClient = document.querySelector(`#${this.props.ui.dom.map}`).getBoundingClientRect();
@@ -140,9 +149,7 @@ class Map extends React.Component {
return (
<MapSites
sites={this.props.domain.sites}
map={this.map}
mapTransformX={this.state.mapTransformX}
mapTransformY={this.state.mapTransformY}
projectPoint={this.projectPoint}
isEnabled={this.props.app.views.sites}
/>
);
@@ -153,9 +160,7 @@ class Map extends React.Component {
<MapShapes
svg={this.svgRef.current}
shapes={this.props.domain.shapes}
map={this.map}
mapTransformX={this.state.mapTransformX}
mapTransformY={this.state.mapTransformY}
projectPoint={this.projectPoint}
/>
)
}
@@ -165,9 +170,7 @@ class Map extends React.Component {
<MapNarratives
svg={this.svgRef.current}
narratives={this.props.domain.narratives}
map={this.map}
mapTransformX={this.state.mapTransformX}
mapTransformY={this.state.mapTransformY}
projectPoint={this.projectPoint}
narrative={this.props.app.narrative}
narrativeProps={this.props.ui.narratives}
onSelect={this.props.methods.onSelect}
@@ -200,9 +203,7 @@ class Map extends React.Component {
locations={this.props.domain.locations}
styleLocation={this.styleLocation}
categories={this.props.domain.categories}
map={this.map}
mapTransformX={this.state.mapTransformX}
mapTransformY={this.state.mapTransformY}
projectPoint={this.projectPoint}
narrative={this.props.app.narrative}
onSelect={this.props.methods.onSelect}
onSelectNarrative={this.props.methods.onSelectNarrative}
@@ -216,9 +217,7 @@ class Map extends React.Component {
<MapSelectedEvents
svg={this.svgRef.current}
selected={this.props.app.selected}
map={this.map}
mapTransformX={this.state.mapTransformX}
mapTransformY={this.state.mapTransformY}
projectPoint={this.projectPoint}
/>
);
}

View File

@@ -5,14 +5,14 @@ import hash from 'object-hash';
import copy from '../js/data/copy.json';
import { formatterWithYear, parseDate } from '../js/utilities';
import TimelineHeader from './presentational/TimelineHeader';
import TimelineHeader from './presentational/Timeline/Header';
import TimelineAxis from './TimelineAxis.jsx';
import TimelineClip from './presentational/TimelineClip';
import TimelineHandles from './presentational/TimelineHandles.js';
import TimelineZoomControls from './presentational/TimelineZoomControls.js';
import TimelineLabels from './presentational/TimelineLabels.js';
import TimelineMarkers from './presentational/TimelineMarkers.js'
import TimelineEvents from './presentational/TimelineEvents.js';
import TimelineClip from './presentational/Timeline/Clip';
import TimelineHandles from './presentational/Timeline/Handles.js';
import TimelineZoomControls from './presentational/Timeline/ZoomControls.js';
import TimelineLabels from './presentational/Timeline/Labels.js';
import TimelineMarkers from './presentational/Timeline/Markers.js'
import TimelineEvents from './presentational/Timeline/Events.js';
import TimelineCategories from './TimelineCategories.jsx';
class Timeline extends React.Component {

BIN
src/components/presentational/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { capitalizeFirstLetter } from '../../js/utilities.js';
import { capitalizeFirstLetter } from '../../../js/utilities.js';
const CardCategory = ({ categoryTitle, categoryLabel, color }) => (
<div className="card-row card-cell category">

View File

@@ -1,7 +1,7 @@
import React from 'react';
import copy from '../../js/data/copy.json';
import { isNotNullNorUndefined } from '../../js/utilities';
import copy from '../../../js/data/copy.json';
import { isNotNullNorUndefined } from '../../../js/utilities';
const CardLocation = ({ language, location }) => {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import CardNarrativeLink from './CardNarrativeLink';
import CardNarrativeLink from './NarrativeLink';
const CardNarrative = (props) => (
<div className="card-row">

View File

@@ -1,9 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import Spinner from './Spinner'
import Img from 'react-image'
import copy from '../../js/data/copy.json'
import Spinner from '../Spinner'
import copy from '../../../js/data/copy.json'
const CardSource = ({ source, isLoading, onClickHandler }) => {
function renderIconText(type) {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import copy from '../../js/data/copy.json';
import copy from '../../../js/data/copy.json';
const CardSummary = ({ language, description, isHighlighted }) => {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import copy from '../../js/data/copy.json';
import copy from '../../../js/data/copy.json';
const CardTags = ({ tags, language }) => {
const tags_lang = copy[language].cardstack.tags;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import copy from '../../js/data/copy.json';
import { isNotNullNorUndefined } from '../../js/utilities';
import copy from '../../../js/data/copy.json';
import { isNotNullNorUndefined } from '../../../js/utilities';
const CardTimestamp = ({ makeTimelabel, language, timestamp }) => {

View File

@@ -1,19 +1,10 @@
import React from 'react';
import { Portal } from 'react-portal';
class MapEvents extends React.Component {
projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1]);
return {
x: this.props.map.latLngToLayerPoint(latLng).x + this.props.mapTransformX,
y: this.props.map.latLngToLayerPoint(latLng).y + this.props.mapTransformY
};
}
getLocationEventsDistribution(location) {
function MapEvents ({ getCategoryColor, categories, projectPoint, styleLocation, narrative, onSelect, svg, locations }){
function getLocationEventsDistribution(location) {
const eventCount = {};
const categories = this.props.categories;
const categories = categories;
categories.forEach(cat => {
eventCount[cat.category] = [];
@@ -26,7 +17,7 @@ class MapEvents extends React.Component {
return eventCount;
}
renderLocation(location) {
function renderLocation(location) {
/**
{
events: [...],
@@ -35,23 +26,23 @@ class MapEvents extends React.Component {
longitude: '32.2'
}
*/
const { x, y } = this.projectPoint([location.latitude, location.longitude]);
// const eventsByCategory = this.getLocationEventsDistribution(location);
const { x, y } = projectPoint([location.latitude, location.longitude]);
// const eventsByCategory = getLocationEventsDistribution(location);
const locCategory = location.events.length > 0 ? location.events[0].category : 'default'
const customStyles = this.props.styleLocation ? this.props.styleLocation(location) : null
const customStyles = styleLocation ? styleLocation(location) : null
const extraStyles = customStyles[0]
const extraRender = customStyles[1]
const styles = ({
fill: this.props.getCategoryColor(locCategory),
fill: getCategoryColor(locCategory),
fillOpacity: 1,
...customStyles[0]
})
// in narrative mode, only render events in narrative
if (this.props.narrative) {
const { steps } = this.props.narrative
if (narrative) {
const { steps } = narrative
const onlyIfInNarrative = e => steps.map(s => s.id).includes(e.id)
const eventsInNarrative = location.events.filter(onlyIfInNarrative)
@@ -64,7 +55,7 @@ class MapEvents extends React.Component {
<g
className="location"
transform={`translate(${x}, ${y})`}
onClick={() => this.props.onSelect(location.events)}
onClick={() => onSelect(location.events)}
>
<circle
className="location-event-marker"
@@ -77,13 +68,11 @@ class MapEvents extends React.Component {
)
}
render() {
return (
<Portal node={this.props.svg}>
{this.props.locations.map(loc => this.renderLocation(loc))}
</Portal>
);
}
return (
<Portal node={svg}>
{locations.map(renderLocation)}
</Portal>
);
}
export default MapEvents;

View File

@@ -1,76 +1,67 @@
import React from 'react'
import { Portal } from 'react-portal'
class MapNarratives extends React.Component {
projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1])
return {
x: this.props.map.latLngToLayerPoint(latLng).x + this.props.mapTransformX,
y: this.props.map.latLngToLayerPoint(latLng).y + this.props.mapTransformY
}
}
getNarrativeStyle(narrativeId) {
const styleName = (narrativeId && narrativeId in this.props.narrativeProps)
function MapNarratives ({ narrativeProps, onSelectNarrative, svg, narrative, narratives, projectPoint }) {
function getNarrativeStyle(narrativeId) {
const styleName = (narrativeId && narrativeId in narrativeProps)
? narrativeId
: 'default'
return this.props.narrativeProps[styleName]
return narrativeProps[styleName]
}
getStepStyle(name) {
function getStepStyle(name) {
if (name === 'None') return null
return this.props.narrativeProps.stepStyles[name]
return narrativeProps.stepStyles[name]
}
hasNoLocation(step) {
function hasNoLocation(step) {
return (step.latitude === '' || step.longitude === '')
}
renderNarrativeStep(idx, n) {
function renderNarrativeStep(idx, n) {
const step = n.steps[idx]
const step2 = n.steps[idx + 1]
// don't draw if one of the steps has no location
if (this.hasNoLocation(step) || this.hasNoLocation(step2))
if (hasNoLocation(step) || hasNoLocation(step2))
return null
// 0 if not in narrative mode, 1 if active narrative, 0.1 if inactive
let styles = {
strokeOpacity: (n === null) ? 0
: (step && (n.id === this.props.narrative.id)) ? 1 : 0.1,
: (step && (n.id === narrative.id)) ? 1 : 0.1,
strokeWidth: 0,
strokeDasharray: 'none',
stroke: 'none'
}
const p1 = this.projectPoint([step.latitude, step.longitude])
const p2 = this.projectPoint([step2.latitude, step2.longitude])
const p1 = projectPoint([step.latitude, step.longitude])
const p2 = projectPoint([step2.latitude, step2.longitude])
if (step) {
if (process.env.features.NARRATIVE_STEP_STYLES) {
const _idx = step.narratives.indexOf(n.id)
const stepStyle = step.narrative___stepStyles[_idx]
return this._renderNarrativeStep(
return _renderNarrativeStep(
p1,
p2,
{ ...styles, ...this.getStepStyle(stepStyle) }
{ ...styles, ...getStepStyle(stepStyle) }
)
// otherwise steps are styled per narrative
} else {
styles = {
...styles,
...this.getNarrativeStyle(n.id)
...getNarrativeStyle(n.id)
}
return this._renderNarrativeStep(p1,p2,styles)
return _renderNarrativeStep(p1,p2,styles)
}
}
}
_renderNarrativeStep(p1, p2, styles) {
function _renderNarrativeStep(p1, p2, styles) {
const { stroke, strokeWidth, strokeDasharray, strokeOpacity } = styles
return (
<line
@@ -80,7 +71,7 @@ class MapNarratives extends React.Component {
y1={p1.y}
y2={p2.y}
markerStart="none"
onClick={() => this.props.onSelectNarrative(n)}
onClick={() => onSelectNarrative(n)}
style={{
strokeWidth,
strokeDasharray,
@@ -93,26 +84,23 @@ class MapNarratives extends React.Component {
}
renderNarrative(n) {
function renderNarrative(n) {
const steps = n.steps.slice(0, n.steps.length - 1)
console.log(n)
return (
<g id={`narrative-${n.id.replace(/ /g,"_")}`} className="narrative">
{steps.map((s, idx) => this.renderNarrativeStep(idx, n))}
{steps.map((s, idx) => renderNarrativeStep(idx, n))}
</g>
)
}
render() {
if (this.props.narrative === null) return (<div />)
if (narrative === null) return (<div />)
return (
<Portal node={this.props.svg}>
{this.props.narratives.map(n => this.renderNarrative(n))}
</Portal>
)
}
return (
<Portal node={svg}>
{narratives.map(n => renderNarrative(n))}
</Portal>
)
}
export default MapNarratives

View File

@@ -2,17 +2,8 @@ import React from 'react';
import { Portal } from 'react-portal';
class MapSelectedEvents extends React.Component {
projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1]);
return {
x: this.props.map.latLngToLayerPoint(latLng).x + this.props.mapTransformX,
y: this.props.map.latLngToLayerPoint(latLng).y + this.props.mapTransformY
};
}
renderMarker (event) {
const { x, y } = this.projectPoint([event.latitude, event.longitude]);
const { x, y } = this.props.projectPoint([event.latitude, event.longitude]);
return (
<g
className="location-marker"
@@ -42,4 +33,4 @@ class MapSelectedEvents extends React.Component {
)
}
}
export default MapSelectedEvents;
export default MapSelectedEvents;

View File

@@ -1,15 +1,7 @@
import React from 'react'
import { Portal } from 'react-portal'
function MapShapes({ svg, map, shapes, mapTransformX, mapTransformY }) {
function projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1])
return {
x: map.latLngToLayerPoint(latLng).x + mapTransformX,
y: map.latLngToLayerPoint(latLng).y + mapTransformY
}
}
function MapShapes({ svg, shapes, projectPoint }) {
function renderShape(shape, lineStyle) {
const lineCoords = []
const points = shape.points

View File

@@ -1,14 +1,6 @@
import React from 'react';
function MapSites({ map, sites, mapTransformX, mapTransformY }) {
function projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1]);
return {
x: map.latLngToLayerPoint(latLng).x + mapTransformX,
y: map.latLngToLayerPoint(latLng).y + mapTransformY
};
}
function MapSites({ sites, projectPoint }) {
function renderSite(site) {
const { x, y } = projectPoint([site.latitude, site.longitude]);

View File

@@ -1,6 +1,6 @@
import React from 'react'
import { connect } from 'react-redux'
import { selectActiveNarrative } from '../../selectors'
import { selectActiveNarrative } from '../../../selectors'
function NarrativeCard ({ narrative }) {
// no display if no narrative

View File

@@ -1,7 +1,7 @@
import React from 'react'
import NarrativeCard from './NarrativeCard'
import NarrativeAdjust from './NarrativeAdjust'
import NarrativeClose from './NarrativeClose'
import Card from './Card'
import Adjust from './Adjust'
import Close from './Close'
export default ({ narrative, methods }) => {
if (!narrative) return null
@@ -12,18 +12,18 @@ export default ({ narrative, methods }) => {
return (
<React.Fragment>
<NarrativeCard narrative={narrative} />
<NarrativeAdjust
<Card narrative={narrative} />
<Adjust
isDisabled={!prevExists}
direction='left'
onClickHandler={methods.onPrev}
/>
<NarrativeAdjust
<Adjust
isDisabled={!nextExists}
direction='right'
onClickHandler={methods.onNext}
/>
<NarrativeClose
<Close
onClickHandler={() => methods.onSelectNarrative(null)}
closeMsg='-- exit from narrative --'
/>

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { formatterWithYear } from '../../js/utilities.js';
import { formatterWithYear } from '../../../js/utilities.js';
const TimelineLabels = ({ dims, timelabels }) => {