diff --git a/.gitignore b/.gitignore index 471ce0b..1297619 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,10 @@ build/ node_modules/ config.js dev.config.js +# ignore all covers but the default +src/components/presentational/covers/ +!src/src/components/presentational/covers/Default.js src/\.DS_Store + +\.DS_Store diff --git a/example.config.js b/example.config.js index 51891ce..27ae9e4 100644 --- a/example.config.js +++ b/example.config.js @@ -11,6 +11,7 @@ module.exports = { INCOMING_DATETIME_FORMAT: '%m/%d/%YT%H:%M', MAPBOX_TOKEN: 'pk.EXAMPLE_MAPBOX_TOKEN', features: { + USE_COVER: false, USE_TAGS: false, USE_SEARCH: false, USE_SITES: true, @@ -32,16 +33,15 @@ module.exports = { new Date(2014, 5, 9), new Date(2018, 1, 6, 23) ] - } } - }, - ui: { - style: { - categories: {}, - shapes: {}, - narratives: {}, - selectedEvent: {}, } } + }, + ui: { + style: { + categories: {}, + shapes: {}, + narratives: {}, + selectedEvent: {} + } } } - diff --git a/src/actions/index.js b/src/actions/index.js index 5f10662..8ee00c0 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -291,6 +291,13 @@ export function markNotificationsRead () { } } +export const TOGGLE_COVER = 'TOGGLE_COVER' +export function toggleCover () { + return { + type: TOGGLE_COVER + } +} + // ERRORS export const FETCH_SOURCE_ERROR = 'FETCH_SOURCE_ERROR' diff --git a/src/components/CategoriesListPanel.jsx b/src/components/CategoriesListPanel.jsx index 64f88e6..a295aa0 100644 --- a/src/components/CategoriesListPanel.jsx +++ b/src/components/CategoriesListPanel.jsx @@ -11,7 +11,6 @@ export default (props) => { function renderCategoryTree () { return (
-

{copy[props.language].toolbar.categories}

{props.categories.map(cat => { return (
  • { return (
    -

    {copy[props.language].toolbar.explore_by_category__title}

    +

    {copy[props.language].toolbar.categories}

    {copy[props.language].toolbar.explore_by_category__description}

    {renderCategoryTree()}
    diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx index 10e1485..3f971f8 100644 --- a/src/components/Dashboard.jsx +++ b/src/components/Dashboard.jsx @@ -13,6 +13,8 @@ import NarrativeControls from './presentational/Narrative/Controls.js' 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 { parseDate } from '../js/utilities' @@ -139,7 +141,9 @@ class Dashboard extends React.Component { actions.toggleInfoPopup()} + methods={{ + onClose: actions.toggleInfoPopup + }} /> ) : null} + {process.env.features.USE_COVER && ( + + {/* enable USE_COVER in config.js features, and customise your header */} + {/* pass 'actions.toggleCover' as a prop to your custom header */} + + + )}

    {paragraph}

    ) +export default ({ ui, app, methods }) => { + function renderIntro () { + return copy[app.language].legend.default.intro.map(txt =>

    {txt}

    ) } - renderCategoryColors () { - const colors = copy[this.props.app.language].legend.view2d.colors.slice(0) - colors.reverse() - return ( -
    - {colors.map((color, idx) => { - return ( -
    -
    - {color.label} -
    - ) - })} + function renderCategoryColors () { + const categories = Object.keys(ui.style.categories).filter(label => label !== 'default') + + return categories.map(category => ( +
    + + + +
    +
    {category}
    +
    - ) + )) } - renderView2DLegend () { + function renderView2DLegend () { return ( -
    - - {this.renderView2DCopy()} +
    +
    + +

    {copy[app.language].legend.default.header}

    +
    + {renderIntro()}
    -
    - - - - - - - - {this.renderCategoryColors()} -
    -
    - - - - - -
    -
    Comunicaciones
    -
    -
    -
    - - - -
    -
    Ataques
    -
    -
    -
    - - - - - - - -
    -
    Rutas de bus
    -
    +
    + {renderCategoryColors()}
    ) } - render () { - return ( -
    {this.renderView2DLegend()}
    - ) - } + return ( +
    {renderView2DLegend()}
    + ) } diff --git a/src/components/StaticPage.js b/src/components/StaticPage.js new file mode 100644 index 0000000..59930c6 --- /dev/null +++ b/src/components/StaticPage.js @@ -0,0 +1,9 @@ +import React from 'react' + +export default ({ showing, children }) => { + return ( +
    + {children} +
    + ) +} diff --git a/src/components/TagListPanel.jsx b/src/components/TagListPanel.jsx index 1d88b73..72582ae 100644 --- a/src/components/TagListPanel.jsx +++ b/src/components/TagListPanel.jsx @@ -63,7 +63,6 @@ class TagListPanel extends React.Component { renderTree () { return (
    -

    {copy[this.props.language].toolbar.tags}

    {this.state.treeComponents.map(c => c)}
    ) @@ -72,7 +71,7 @@ class TagListPanel extends React.Component { render () { return (
    -

    {copy[this.props.language].toolbar.explore_by_tag__title}

    +

    {copy[this.props.language].toolbar.tags}

    {copy[this.props.language].toolbar.explore_by_tag__description}

    {this.renderTree()}
    diff --git a/src/components/presentational/covers/Default.js b/src/components/presentational/covers/Default.js new file mode 100644 index 0000000..e8b042d --- /dev/null +++ b/src/components/presentational/covers/Default.js @@ -0,0 +1,16 @@ +import React from 'react' + +export default ({ showAppHandler }) => ( +
    +

    Here's an example cover.

    +

    Replace it with a more descriptive one:

    +
      +
    • Create a new component in components/presentational/covers.
    • +
    • Import in in components/Dashboard.jsx in the render function.
    • +
    +

    +
    + +
    +
    +) diff --git a/src/js/data/copy.json b/src/js/data/copy.json index 47e642b..3e7f245 100644 --- a/src/js/data/copy.json +++ b/src/js/data/copy.json @@ -90,6 +90,14 @@ { "class": "category_group03", "label": "Category Group 03" }, { "class": "other", "label": "Other categories" } ] + }, + "default": { + "header": "Navigating the Platform", + "intro": [ + "Each event represents an occurence that is distinct in either time, space, or both. An event is represented by a coloured circle on both the map and the timeline.", + "Select an event to reveal its content and sources. You can filter events by category or other specified filters in the top left toolbar.", + "Narratives compose events to reveal logical threads that emerge from them. Transition to narrative mode by selecting a narrative from the top left dashboard icon." + ] } }, "toolbar": { diff --git a/src/js/utilities.js b/src/js/utilities.js index 42bc3b9..8d04788 100644 --- a/src/js/utilities.js +++ b/src/js/utilities.js @@ -126,3 +126,13 @@ export function urlFromEnv (ext) { return null } } + +export function toggleFlagAC (flag) { + return (appState) => ({ + ...appState, + flags: { + ...appState.flags, + [flag]: !appState.flags[flag] + } + }) +} diff --git a/src/reducers/app.js b/src/reducers/app.js index e4d7811..83f2187 100644 --- a/src/reducers/app.js +++ b/src/reducers/app.js @@ -1,6 +1,6 @@ /* global d3 */ import initial from '../store/initial.js' -import { parseDate } from '../js/utilities' +import { parseDate, toggleFlagAC } from '../js/utilities' import { UPDATE_HIGHLIGHTED, @@ -19,6 +19,7 @@ import { TOGGLE_FETCHING_SOURCES, TOGGLE_INFOPOPUP, TOGGLE_NOTIFICATIONS, + TOGGLE_COVER, FETCH_ERROR, FETCH_SOURCE_ERROR } from '../actions' @@ -189,16 +190,6 @@ function toggleLanguage (appState, action) { }) } -function toggleSites (appState, action) { - return { - ...appState, - flags: { - ...appState.flags, - isShowingSites: !appState.flags.isShowingSites - } - } -} - function updateSource (appState, action) { return { ...appState, @@ -214,37 +205,12 @@ function fetchError (state, action) { } } -function toggleFetchingDomain (appState, action) { - return Object.assign({}, appState, { - flags: Object.assign({}, appState.flags, { - isFetchingDomain: !appState.flags.isFetchingDomain - }) - }) -} - -function toggleFetchingSources (appState, action) { - return Object.assign({}, appState, { - flags: Object.assign({}, appState.flags, { - isFetchingSources: !appState.flags.isFetchingSources - }) - }) -} - -function toggleInfoPopup (appState, action) { - return Object.assign({}, appState, { - flags: Object.assign({}, appState.flags, { - isInfopopup: !appState.flags.isInfopopup - }) - }) -} - -function toggleNotifications (appState, action) { - return Object.assign({}, appState, { - flags: Object.assign({}, appState.flags, { - isNotification: !appState.flags.isNotification - }) - }) -} +const toggleSites = toggleFlagAC('isShowingSites') +const toggleFetchingDomain = toggleFlagAC('isFetchingDomain') +const toggleFetchingSources = toggleFlagAC('isFetchingSources') +const toggleInfoPopup = toggleFlagAC('isInfopopup') +const toggleNotifications = toggleFlagAC('isNotification') +const toggleCover = toggleFlagAC('isCover') function fetchSourceError (appState, action) { return { @@ -278,20 +244,24 @@ function app (appState = initial.app, action) { return updateSource(appState, action) case RESET_ALLFILTERS: return resetAllFilters(appState, action) + /* toggles */ case TOGGLE_LANGUAGE: return toggleLanguage(appState, action) case TOGGLE_SITES: - return toggleSites(appState, action) + return toggleSites(appState) + case TOGGLE_FETCHING_DOMAIN: + return toggleFetchingDomain(appState) + case TOGGLE_FETCHING_SOURCES: + return toggleFetchingSources(appState) + case TOGGLE_INFOPOPUP: + return toggleInfoPopup(appState) + case TOGGLE_NOTIFICATIONS: + return toggleNotifications(appState) + case TOGGLE_COVER: + return toggleCover(appState) + /* errors */ case FETCH_ERROR: return fetchError(appState, action) - case TOGGLE_FETCHING_DOMAIN: - return toggleFetchingDomain(appState, action) - case TOGGLE_FETCHING_SOURCES: - return toggleFetchingSources(appState, action) - case TOGGLE_INFOPOPUP: - return toggleInfoPopup(appState, action) - case TOGGLE_NOTIFICATIONS: - return toggleNotifications(appState, action) case FETCH_SOURCE_ERROR: return fetchSourceError(appState, action) default: diff --git a/src/scss/cover.scss b/src/scss/cover.scss new file mode 100644 index 0000000..a033eb7 --- /dev/null +++ b/src/scss/cover.scss @@ -0,0 +1,26 @@ +.cover-container { + position: absolute; + top: -100%; + left: 0; + background-color: black; + width: 100%; + height: 100%; + opacity: 0.95; + transition: top 0.4s ease; + z-index: $overheader + 1; + + color: $offwhite; + + &.showing { + top: 0; + left: 0; + } +} + +.default-cover-container { + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + height: 100%; +} \ No newline at end of file diff --git a/src/scss/infopopup.scss b/src/scss/infopopup.scss index 5b75683..fd9c64e 100644 --- a/src/scss/infopopup.scss +++ b/src/scss/infopopup.scss @@ -24,87 +24,52 @@ opacity: 0; } - .legend-section { - width: 300px; - padding-left: 60px; - height: 40px; - display: inline-block; - - svg { - width: 100px; - float: left; - display: inline-block; - } - - .legend-labels { - float: left; - display: inline-block; - width: calc(100% - 100px); - - .label { - display: block; - font-size: $xsmall; - margin-top: 10px; - margin-left: 10px; - - .color-category { - width: 8px; - height: 8px; - border-radius: 10px; - display: inline-block; - margin: 0px 5px 0 0; - } - } - } - - &:first-child { - .legend-labels .label { - margin-top: 0; - } - } + .legend { + display: flex; + flex-direction: column; } + .legend-header { + display: flex; + flex-direction: row; + h2 { + display: flex; + font-size: 12pt; + letter-spacing: 2px; + margin: 0; + } + } .side-menu-burg { position: absolute; right: 8px; top: 10px; } - .legend-item { - display: block; - width: 100%; - display: inline-block; - margin-bottom: 3px; - padding-left: 80px; + .legend-container { + height: 100%; + display: flex; + flex-direction: column; + } - .item-label { - line-height: 15px; - height: 15px; - font-size: $normal; - } + .legend-section { + width: 300px; + height: 25px; + display: flex; + align-items: center; - .color-marker { - display: inline-block; - width: 15px; - height: 15px; + svg { + width: 60px; float: left; - margin: 0 10px 0 0; - border-radius: 15px; - - &.victims { background-color: #C90500; } - &.military { background-color: #319C31; } - &.nonstate { background-color: #AC28AC; } - &.state-police { background-color: #0000BF; } - &.iguala-municipal-police { background-color: #00558D; } - &.federal-police { background-color: #5756A2; } - &.huitzuco-municipal-police { background-color: #4ECAC1; } - &.cocula-municipal-police { background-color: #095959; } - &.ambulance { background-color: #ffffff; } - &.other { background-color: #D3CE2A; } - &.drivers { background-color: #822519; } - &.communications { background-color: #a6a6a6; } - &.GIEI { background-color: #ffffff; } - &.PGR { background-color: #000000; } + display: inline-block; } + + .legend-labels { + display: flex; + + .label { + font-size: $xsmall; + } + } + } } diff --git a/src/scss/main.scss b/src/scss/main.scss index e2d7a82..21656c9 100644 --- a/src/scss/main.scss +++ b/src/scss/main.scss @@ -16,3 +16,4 @@ @import 'notification'; @import 'scene'; @import 'mediaplayer'; +@import 'cover'; diff --git a/src/store/initial.js b/src/store/initial.js index f3fa4cc..598ebf8 100644 --- a/src/store/initial.js +++ b/src/store/initial.js @@ -52,7 +52,7 @@ const initial = { map: { anchor: [31.356397, 34.784818], startZoom: 11, - minZoom: 7, + minZoom: 6, maxZoom: 18, bounds: null, maxBounds: [[180, -180], [-180, 180]] @@ -84,9 +84,9 @@ const initial = { flags: { isFetchingDomain: false, isFetchingSources: false, - + isCover: true, isCardstack: true, - isInfopopup: false, + isInfopopup: true, isShowingSites: true } },