From eff13c3d9260835bf8b0b586290e67719518e958 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 28 Oct 2020 17:54:59 +0100 Subject: [PATCH] Feature/infopopup (#173) * make intropopup possible * aesthetic changes * lint * correct infopopup styles --- src/actions/index.js | 7 ++ src/common/data/copy.json | 8 +- src/components/InfoPopup.jsx | 117 +++---------------------- src/components/Layout.js | 31 +++++-- src/components/TemplateCover.js | 4 +- src/components/presentational/Popup.js | 21 +++++ src/reducers/app.js | 4 + src/scss/_variables.scss | 2 + src/scss/infopopup.scss | 25 ++++-- src/store/initial.js | 3 + 10 files changed, 97 insertions(+), 125 deletions(-) create mode 100644 src/components/presentational/Popup.js diff --git a/src/actions/index.js b/src/actions/index.js index 718277a..aaea8dc 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -305,6 +305,13 @@ export function toggleInfoPopup () { } } +export const TOGGLE_INTROPOPUP = 'TOGGLE_INTROPOPUP' +export function toggleIntroPopup () { + return { + type: TOGGLE_INTROPOPUP + } +} + export const TOGGLE_NOTIFICATIONS = 'TOGGLE_NOTIFICATIONS' export function toggleNotifications () { return { diff --git a/src/common/data/copy.json b/src/common/data/copy.json index 7311a2c..ee9cb24 100644 --- a/src/common/data/copy.json +++ b/src/common/data/copy.json @@ -94,9 +94,11 @@ "default": { "header": "Navigating the Platform", "intro": [ - "Open source research by [Bellingcat](https://bellingcat.com).
Software and spatialisation by [Forensic Architecture](https://forensic-architecture.org).", - "Each event represents an occurence that is distinct in time or 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." + "Each small **dot** represents a **datapoint**, or incident. Click on a dot to see details. Hover over a larger ‘**cluster**’ dot to see how many events it represents.", + "Zoom in either with a mouse-scroll or by clicking a ‘cluster’ dot.", + "Use **filters** and **categories** to segment the data. Selecting certain filters and categories will show only the datapoints that relate to them. If no filters or categories are selected, all the datapoints are displayed.", + "Selecting more than one filter will introduce colour-coded datapoints, which allow you to compare types of incident across time and space. This feature works up to a maximum of six filters.", + "Use the left and right arrows to move back and forward through time. Use the handles on the right to select a date range." ], "notation": "Combinations of colours within a circle indicate multiple events in a single location.", "arrows": "Use the left/right arrows on the keboard to move back and forth between events in time." diff --git a/src/components/InfoPopup.jsx b/src/components/InfoPopup.jsx index de0fa78..52435d3 100644 --- a/src/components/InfoPopup.jsx +++ b/src/components/InfoPopup.jsx @@ -1,110 +1,13 @@ import React from 'react' -import marked from 'marked' +import Popup from './presentational/Popup' import copy from '../common/data/copy.json' -export default ({ ui, app, methods }) => { - function renderIntro () { - var introCopy = copy[app.language].legend.default.intro - if (process.env.store.text && process.env.store.text.introCopy) introCopy = process.env.store.text.introCopy - return introCopy.map(txt =>

) - } - - function renderHalfWithDot () { - // extract category colors from store for combined display. - const categoryKeys = Object.keys(ui.style.categories) - let firstFill = 'red' - let secondFill = 'blue' - if (categoryKeys.length >= 1) { - firstFill = ui.style.categories[categoryKeys[0]] - } - if (categoryKeys.length >= 2) { - secondFill = ui.style.categories[categoryKeys[1]] - } - - return [ - , - - - - - 2 - - - ] - } - - function renderCategoryColors () { - const categories = Object.keys(ui.style.categories).filter(label => label !== 'default') - categories.reverse() - return categories.map(category => ( -

- - - -
-
{category}
-
-
- )) - } - - function renderArrow (strokeFill) { - return ( - - - - - - ) - } - - function renderView2DLegend () { - return ( -
-
- -

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

-
- {renderIntro()} -
- {renderCategoryColors()} -
-
-
-
-
- {renderHalfWithDot()} -
-
- {copy[app.language].legend.default.notation} -
-
-
-
-
-

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

-
- - { - ui.style.arrows ? ( - - Object.keys(ui.style.arrows).map(arrowName => ( -
- {renderArrow(ui.style.arrows[arrowName])} -
-
{arrowName}
-
-
- )) - ) : null - } - -
- ) - } - - return ( -
{renderView2DLegend()}
- ) -} +export default ({ isOpen, onClose, language, styles }) => ( + +) diff --git a/src/components/Layout.js b/src/components/Layout.js index 17b0030..ab87b1f 100644 --- a/src/components/Layout.js +++ b/src/components/Layout.js @@ -13,7 +13,8 @@ import Toolbar from './Toolbar/Layout' import CardStack from './CardStack.jsx' // import {CardStack} from '@forensic-architecture/design-system' import NarrativeControls from './presentational/Narrative/Controls.js' -import InfoPopUp from './InfoPopup.jsx' +import InfoPopup from './InfoPopup.jsx' +import Popup from './presentational/Popup' import Timeline from './Timeline.jsx' import Notification from './Notification.jsx' import StateOptions from './StateOptions.jsx' @@ -239,7 +240,7 @@ class Dashboard extends React.Component { } render () { - const { actions, app, domain, ui, features } = this.props + const { actions, app, domain, features } = this.props if (isMobile || window.innerWidth < 600) { const msg = 'This platform is not suitable for mobile. Please re-visit the site on a device with a larger screen.' return ( @@ -259,6 +260,13 @@ class Dashboard extends React.Component { ) } + const popupStyles = { + fontSize: 24, + height: `calc(100vh - ${app.timeline.dimensions.height}px)`, + width: '40vw', + bottom: app.timeline.dimensions.height + } + return (
- + {app.debug ?
-
+ {Array.isArray(this.props.cover.description) + ? this.props.cover.description.map(e =>
) + :
} {videos ? (
diff --git a/src/components/presentational/Popup.js b/src/components/presentational/Popup.js new file mode 100644 index 0000000..3170110 --- /dev/null +++ b/src/components/presentational/Popup.js @@ -0,0 +1,21 @@ +import React from 'react' +import marked from 'marked' + +export default ({ + content = [], + styles = {}, + isOpen = true, + onClose, + title, + theme = 'light' +}) => ( +
+
+
+ +

{title}

+
+ {content.map(t =>
)} +
+
+) diff --git a/src/reducers/app.js b/src/reducers/app.js index e56275d..04e125b 100644 --- a/src/reducers/app.js +++ b/src/reducers/app.js @@ -18,6 +18,7 @@ import { TOGGLE_FETCHING_DOMAIN, TOGGLE_FETCHING_SOURCES, TOGGLE_INFOPOPUP, + TOGGLE_INTROPOPUP, TOGGLE_NOTIFICATIONS, TOGGLE_COVER, FETCH_ERROR, @@ -205,6 +206,7 @@ const toggleSites = toggleFlagAC('isShowingSites') const toggleFetchingDomain = toggleFlagAC('isFetchingDomain') const toggleFetchingSources = toggleFlagAC('isFetchingSources') const toggleInfoPopup = toggleFlagAC('isInfopopup') +const toggleIntroPopup = toggleFlagAC('isIntropopup') const toggleNotifications = toggleFlagAC('isNotification') const toggleCover = toggleFlagAC('isCover') @@ -287,6 +289,8 @@ function app (appState = initial.app, action) { return toggleFetchingSources(appState) case TOGGLE_INFOPOPUP: return toggleInfoPopup(appState) + case TOGGLE_INTROPOPUP: + return toggleIntroPopup(appState) case TOGGLE_NOTIFICATIONS: return toggleNotifications(appState) case TOGGLE_COVER: diff --git a/src/scss/_variables.scss b/src/scss/_variables.scss index 71ef4e2..3a71324 100644 --- a/src/scss/_variables.scss +++ b/src/scss/_variables.scss @@ -1,6 +1,7 @@ $event_default: red; $offwhite: #efefef; +$offwhite-transparent: rgba(239,239,239, 0.9); $lightwhite: #dfdfdf; $midwhite: #a0a0a0; $darkwhite: darken($midwhite, 15%); @@ -10,6 +11,7 @@ $green: rgb(61, 241, 79); $midgrey: rgb(44, 44, 44); $darkgrey: #232323; $black: #000000; +$black-transparent: rgba(0,0,0,0.7); // Category colors $default: red; diff --git a/src/scss/infopopup.scss b/src/scss/infopopup.scss index 179bf55..6e4451b 100644 --- a/src/scss/infopopup.scss +++ b/src/scss/infopopup.scss @@ -5,7 +5,7 @@ box-shadow: 10px -10px 38px rgba(0, 0, 0, 0.3), 10px 15px 12px rgba(0, 0, 0, 0.22); color: $darkgrey; position: absolute; - background: $offwhite; + background: $offwhite-transparent; bottom: $timeline-height; left: $toolbar-width; border: 3px solid $offwhite; @@ -23,6 +23,24 @@ opacity: 0; } + .side-menu-burg { + position: absolute; + right: 8px; + top: 10px; + &.light { + &.is-active span:after, + &.is-active span:before { + background: black; + } + } + } + + &.dark { + background: $black-transparent; + color: white; + } + + .legend { display: flex; flex-direction: column; @@ -38,11 +56,6 @@ margin: 0; } } - .side-menu-burg { - position: absolute; - right: 8px; - top: 10px; - } .legend-container { height: 100%; diff --git a/src/store/initial.js b/src/store/initial.js index 47eeebe..26e306c 100644 --- a/src/store/initial.js +++ b/src/store/initial.js @@ -93,6 +93,7 @@ const initial = { isCover: true, isCardstack: true, isInfopopup: false, + isIntropopup: false, isShowingSites: true }, cover: { @@ -170,4 +171,6 @@ if (process.env.store) { appStore.app.timeline.range[0] = new Date(appStore.app.timeline.range[0]) appStore.app.timeline.range[1] = new Date(appStore.app.timeline.range[1]) +appStore.app.flags.isIntropopup = !!appStore.app.intro + export default appStore