diff --git a/src/assets/transparent.png b/src/assets/transparent.png new file mode 100644 index 0000000..31726f4 Binary files /dev/null and b/src/assets/transparent.png differ diff --git a/src/components/Card.jsx b/src/components/Card.jsx index 7829616..2e996e9 100644 --- a/src/components/Card.jsx +++ b/src/components/Card.jsx @@ -21,19 +21,13 @@ class Card extends React.Component { constructor(props) { super(props) this.state = { - isHighlighted: false + isOpen: false } } toggle() { this.setState({ - isHighlighted: !this.state.isHighlighted - }, () => { - if (!this.state.isHighlighted) { - this.props.onHighlight(this.props.event) - } else { - this.props.onHighlight(null) - } + isOpen: !this.state.isOpen }) } @@ -49,13 +43,14 @@ class Card extends React.Component { const categoryLabel = this.props.event.category const color = this.props.getCategoryColor(this.props.event.category) - return ( - - ) + return null + // return ( + // + // ) } renderSummary() { @@ -63,7 +58,7 @@ class Card extends React.Component { ) } @@ -96,7 +91,7 @@ class Card extends React.Component { const source_lang = copy[this.props.language].cardstack.sources return ( -
+

{source_lang}:

{this.props.event.sources.map(source => ( -
+
+
{this.renderTimestamp()} {this.renderLocation()}
{this.renderCategory()} -
{this.renderSummary()}
) } - renderContent() { - if (this.state.isHighlighted) { - return ( -
- {this.renderTags()} - {this.renderSources()} - {this.renderNarrative()} -
- ) - } else { - return
- } + renderExtra() { + return ( +
+ {this.renderTags()} + {this.renderSources()} + {this.renderNarrative()} +
+ ) } renderCaret() { return ( this.toggle()} - isHighlighted={this.state.isHighlighted} + isOpen={this.state.isOpen} /> ) } render() { + const { isSelected } = this.props return ( -
  • - {this.renderHeader()} - {this.renderContent()} - {this.renderCaret()} +
  • + {this.renderMain()} + {this.state.isOpen ? this.renderExtra() : null} + {isSelected ? this.renderCaret() : null}
  • ) } diff --git a/src/components/CardStack.jsx b/src/components/CardStack.jsx index f25e68a..4d37399 100644 --- a/src/components/CardStack.jsx +++ b/src/components/CardStack.jsx @@ -9,13 +9,18 @@ import { } from '../js/utilities.js' class CardStack extends React.Component { - renderCards(events) { - return events.map(event => ( + renderCards(events, selections) { + // if no selections provided, select all + if (!selections) + selections = events.map(e => true) + + return events.map((event, idx) => ( (idx === 0)) + + return this.renderCards(showing, selections) } renderCardStackHeader() { diff --git a/src/components/Timeline.jsx b/src/components/Timeline.jsx index ae42fb2..28aba21 100644 --- a/src/components/Timeline.jsx +++ b/src/components/Timeline.jsx @@ -34,18 +34,20 @@ class Timeline extends React.Component { } render() { + const { isNarrative, app, ui } = this.props let classes = `timeline-wrapper ${(this.state.isFolded) ? ' folded' : ''}`; - classes += (this.props.app.narrative !== null) ? ' narrative-mode' : ''; + classes += (app.narrative !== null) ? ' narrative-mode' : ''; return (
    { this.onClickArrow(); }} + hideInfo={isNarrative} />
    -
    +
    ); @@ -54,6 +56,7 @@ class Timeline extends React.Component { function mapStateToProps(state) { return { + isNarrative: !!state.app.narrative, domain: { events: state.domain.events, categories: selectors.selectCategories(state), diff --git a/src/components/presentational/TimelineHeader.js b/src/components/presentational/TimelineHeader.js index d75a605..f9ece09 100644 --- a/src/components/presentational/TimelineHeader.js +++ b/src/components/presentational/TimelineHeader.js @@ -1,11 +1,11 @@ import React from 'react'; -const TimelineHeader = ({ title, date0, date1, onClick }) => ( -
    -
    onClick()}> -

    +const TimelineHeader = ({ title, date0, date1, onClick, hideInfo }) => ( +
    +
    onClick()}> +

    -
    +

    {title}

    {date0} - {date1}

    diff --git a/src/js/utilities.js b/src/js/utilities.js index 751a93d..924e1f5 100644 --- a/src/js/utilities.js +++ b/src/js/utilities.js @@ -79,6 +79,29 @@ export function compareTimestamp (a, b) { return (parseTimestamp(a.timestamp) > parseTimestamp(b.timestamp)); } +/** + * Inset the full source represenation from 'allSources' into an event. The + * function is 'curried' to allow easy use with maps. To use for a single + * source, call with two sets of parentheses: + * const src = insetSourceFrom(sources)(anEvent) + */ +export function insetSourceFrom(allSources) { + return (event) => { + let sources + if (!event.sources) { + sources = [] + } else { + sources = event.sources.map(id => ( + allSources.hasOwnProperty(id) ? allSources[id] : null + )) + } + return { + ...event, + sources + } + } + +} /** * Debugging function: put in place of a mapStateToProps function to diff --git a/src/scss/card.scss b/src/scss/card.scss index 8979937..a801f0e 100644 --- a/src/scss/card.scss +++ b/src/scss/card.scss @@ -2,10 +2,10 @@ box-sizing: border-box; margin: 1px 0 0 0; padding: 15px; - border: 1px solid rgba(0, 0, 0, 0); - border-radius: 3px; + border: 1px solid $black; + // border-radius: 3px; transition: 0.2 ease; - background: $offwhite; + background: $darkwhite; color: $darkgrey; box-shadow: 0 19px 19px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22); font-size: $large; @@ -39,10 +39,13 @@ .card-row, .card-col { display: flex; flex-direction: row; - border-bottom: 1px solid $lightwhite; margin: 5px 0 10px 0; padding-bottom: 10px; + &.details { + border-bottom: 1px solid $lightwhite; + } + .card-cell { flex: 1; } @@ -120,6 +123,7 @@ height: 0; overflow: hidden; } + } .card-toggle p { @@ -197,6 +201,7 @@ .summary { overflow: auto; margin-top: 0; + border-bottom: none; } .tag { @@ -204,4 +209,12 @@ margin: 0; margin-right: 5px; } + + &.selected { + background: $offwhite; + } + + .card-row { + border-color: darkgray; + } } diff --git a/src/scss/cardstack.scss b/src/scss/cardstack.scss index da6ca92..0b83da3 100644 --- a/src/scss/cardstack.scss +++ b/src/scss/cardstack.scss @@ -11,17 +11,16 @@ $timeline-height: 170px; right: 10px; max-height: calc(100% - 208px); height: auto; - overflow: auto; + overflow: hidden; box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22); z-index: $header; color: white; - -webkit-font-smoothing: antialiased; &.narrative-mode { right: auto; left: 10px; top: $narrative-info-max-height + 12px; - height: calc(100% - #{$narrative-info-max-height} - #{$timeline-height}); + height: calc(100% - #{$narrative-info-max-height} - #{$timeline-height} - 12px); } &.full-height { diff --git a/src/scss/timeline.scss b/src/scss/timeline.scss index 2205ce1..24666a4 100644 --- a/src/scss/timeline.scss +++ b/src/scss/timeline.scss @@ -1,4 +1,3 @@ - .timeline-wrapper { position: fixed; box-sizing: border-box; @@ -67,6 +66,10 @@ } .timeline-info { + &.hidden { + display: none; + } + width: calc(#{$card-width} - 20px); position: absolute; margin-top: -70px; margin-left: 10px; diff --git a/src/selectors/index.js b/src/selectors/index.js index 76cb8ad..d560a00 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -1,5 +1,5 @@ import { createSelector} from 'reselect' -import { parseTimestamp, compareTimestamp } from '../js/utilities' +import { parseTimestamp, compareTimestamp, insetSourceFrom } from '../js/utilities' // Input selectors export const getEvents = state => state.domain.events @@ -22,6 +22,8 @@ export const getTagTree = state => state.domain.tags export const getTagsFilter = state => state.app.filters.tags export const getTimeRange = state => state.app.filters.timerange + + /** * Some handy helpers */ @@ -90,8 +92,8 @@ export const selectEvents = createSelector( * and if TAGS are being used, select them if their tags are enabled */ export const selectNarratives = createSelector( - [getEvents, getNarratives, getTagsFilter, getTimeRange], - (events, narrativesMeta, tagFilters, timeRange) => { + [getEvents, getNarratives, getTagsFilter, getTimeRange, getSources], + (events, narrativesMeta, tagFilters, timeRange, sources) => { const narratives = {} const narrativeSkeleton = id => ({ id, steps: [] }) @@ -109,7 +111,8 @@ export const selectNarratives = createSelector( // add evt to steps if (isInNarrative) - narratives[narrative].steps.push(evt) + // NB: insetSourceFrom is a 'curried' function to allow with maps + narratives[narrative].steps.push(insetSourceFrom(sources)(evt)) }) }) @@ -173,6 +176,8 @@ export const selectLocations = createSelector( } ) + + /** * Of all the sources, select those that are relevant to the selected events. */ @@ -183,21 +188,7 @@ export const selectSelected = createSelector( return [] } - // NB: return source object if exists, otherwise null - const srcs = selected - .map(e => e.sources) - .map(_sources => { - if (!_sources) return [] - return _sources.map(id => ( - sources.hasOwnProperty(id) ? sources[id] : null - )) - } - ) - - return selected.map((s, idx) => ({ - ...s, - sources: srcs[idx] - })) + return selected.map(insetSourceFrom(sources)) } )