add satellite overlay toggle

This commit is contained in:
hgrsd
2022-03-22 22:57:56 -04:00
parent 1b30f320b5
commit 9b7e02ef61
9 changed files with 211 additions and 55 deletions

View File

@@ -2,11 +2,12 @@ const one_day = 1440;
module.exports = {
title: "ukraine",
display_title: "Civilian Harm in Ukraine",
SERVER_ROOT: 'https://ukraine.bellingcat.com/ukraine-server',
SERVER_ROOT: "https://ukraine.bellingcat.com/ukraine-server",
EVENTS_EXT: "/api/ukraine/export_events/deeprows",
SOURCES_EXT: "/api/ukraine/export_sources/deepids",
ASSOCIATIONS_EXT: "/api/ukraine/export_associations/deeprows",
MAPBOX_TOKEN: "pk.eyJ1IjoiYmVsbGluZ2NhdC1tYXBib3giLCJhIjoiY2tleW0wbWliMDA1cTJ5bzdkbTRraHgwZSJ9.GJQkjPzj8554VhR5SPsfJg",
MAPBOX_TOKEN:
"pk.eyJ1IjoiYmVsbGluZ2NhdC1tYXBib3giLCJhIjoiY2tleW0wbWliMDA1cTJ5bzdkbTRraHgwZSJ9.GJQkjPzj8554VhR5SPsfJg",
// MEDIA_EXT: "/api/media",
DATE_FMT: "MM/DD/YYYY",
TIME_FMT: "HH:mm",
@@ -16,7 +17,7 @@ module.exports = {
debug: true,
map: {
// anchor: [49.02421913, 31.43836003],
anchor: [48.3326259, 33.199514470],
anchor: [48.3326259, 33.19951447],
maxZoom: 18,
minZoom: 4,
startZoom: 6,
@@ -24,7 +25,7 @@ module.exports = {
},
cluster: { radius: 50, minZoom: 5, maxZoom: 12 },
associations: {
defaultCategory: "Weapon System"
defaultCategory: "Weapon System",
},
timeline: {
dimensions: {
@@ -32,15 +33,12 @@ module.exports = {
contentHeight: 150,
},
zoomLevels: [
{ label: 'Zoom to 1 week', duration: 7 * one_day },
{ label: 'Zoom to 2 weeks', duration: 14 * one_day },
{ label: 'Zoom to 1 month', duration: 31 * one_day },
{ label: 'Zoom to 3 months', duration: 3 * 31 * one_day },
],
range: [
new Date(Date.now() - (14 * (60 * 60 * 1000 * 24))),
new Date()
{ label: "Zoom to 1 week", duration: 7 * one_day },
{ label: "Zoom to 2 weeks", duration: 14 * one_day },
{ label: "Zoom to 1 month", duration: 31 * one_day },
{ label: "Zoom to 3 months", duration: 3 * 31 * one_day },
],
range: [new Date(Date.now() - 14 * (60 * 60 * 1000 * 24)), new Date()],
// rangeLimits: []
},
intro: [
@@ -71,8 +69,8 @@ module.exports = {
"## A Note on Bellingcat's Global Authentication Project",
"The Global Authentication Project consists of a wide community of open source researchers assisting in Bellingcat research through structured tasks and feedback. Our aim is to authenticate events taking place around the world and fill in the gaps of knowledge that exist, particularly in situations where there are vast quantities of data. In creating a community for those interested in open source research, we are fostering Bellingcat's original aim of solving problems **together**, to diversify our investigations and promote the use of these skills. For this dataset, we are working with many individuals who have Ukrainian language skills and others with local contextual knowledge of the events and places seen on the map. Other participants include individuals skilled in geolocation and chronolocation, with all contributions being vetted by Bellingcat researchers. As we expand the Global Authentication Project in the coming months, more information will be available on our website and Twitter.",
"## Feedback",
"This map will continue to change and be updated for the duration of this conflict. We welcome feedback on our methodology, data collection and take transparency seriously. Should you have any direct feedback about the platform, please indicate it on this [form](https://forms.gle/cV2YAojBoh6h4T3XA)."
]
"This map will continue to change and be updated for the duration of this conflict. We welcome feedback on our methodology, data collection and take transparency seriously. Should you have any direct feedback about the platform, please indicate it on this [form](https://forms.gle/cV2YAojBoh6h4T3XA).",
],
},
toolbar: {
panels: {
@@ -87,30 +85,43 @@ module.exports = {
// label: "Unverified",
// description: "todo",
// }
}
}
},
},
},
spotlights: {}
spotlights: {},
},
ui: {
coloring: {
mode: "STATIC",
maxNumOfColors: 9,
defaultColor: "#dfdfdf",
colors: ["#7E57C2", "#F57C00", "#FFEB3B", "#D34F73", "#08B2E3", "#A1887F", "#90A4AE", "#E57373", "#80CBC4"],
colors: [
"#7E57C2",
"#F57C00",
"#FFEB3B",
"#D34F73",
"#08B2E3",
"#A1887F",
"#90A4AE",
"#E57373",
"#80CBC4",
],
},
card: {
layout: {
template: "sourced"
}
template: "sourced",
},
},
carto: {
eventRadius: 8
eventRadius: 8,
},
timeline: {
eventRadius: 9
eventRadius: 9,
},
tiles: {
current: "bellingcat-mapbox/cl0qnou2y003m15s8ieuyhgsy",
default: "bellingcat-mapbox/cl0qnou2y003m15s8ieuyhgsy",
},
tiles: 'bellingcat-mapbox/cl0qnou2y003m15s8ieuyhgsy'
},
features: {
USE_CATEGORIES: false,
@@ -123,6 +134,7 @@ module.exports = {
USE_SHAPES: false,
USE_COVER: true,
USE_INTRO: false,
USE_SATELLITE_OVERLAY_TOGGLE: true,
USE_SEARCH: false,
USE_SITES: false,
ZOOM_TO_TIMEFRAME_ON_TIMELINE_CLICK: one_day,
@@ -130,7 +142,7 @@ module.exports = {
USE_MEDIA_CACHE: false,
GRAPH_NONLOCATED: false,
NARRATIVE_STEP_STYLES: false,
CUSTOM_EVENT_FIELDS: []
CUSTOM_EVENT_FIELDS: [],
},
},
};
};

View File

@@ -400,3 +400,17 @@ export function fetchSourceError(msg) {
msg,
};
}
export const USE_SATELLITE_TILES_OVERLAY = "USE_SATELLITE_TILES_OVERLAY";
export function useSatelliteTilesOverlay() {
return {
type: USE_SATELLITE_TILES_OVERLAY,
};
}
export const RESET_TILES_OVERLAY = "RESET_TILES_OVERLAY";
export function resetTilesOverlay() {
return {
type: RESET_TILES_OVERLAY,
};
}

View File

@@ -1,5 +1,9 @@
{
"es-MX": {
"tiles": {
"default": "Predeterminado",
"satellite": "Satélite"
},
"loading": "Cargando...",
"legend": {
"view2d": {
@@ -90,6 +94,10 @@
}
},
"en-US": {
"tiles": {
"default": "Default",
"satellite": "Satellite"
},
"loading": "Loading...",
"legend": {
"view2d": {

View File

@@ -1,4 +1,5 @@
/* global L */
import { bindActionCreators } from "redux";
import "leaflet";
import React from "react";
import { Portal } from "react-portal";
@@ -6,6 +7,7 @@ import Supercluster from "supercluster";
import { isMobileOnly } from "react-device-detect";
import { connect } from "react-redux";
import * as actions from "../../../actions";
import * as selectors from "../../../selectors";
import Sites from "./atoms/Sites";
@@ -15,6 +17,7 @@ import Clusters from "./atoms/Clusters";
import SelectedEvents from "./atoms/SelectedEvents";
import Narratives from "./atoms/Narratives";
import DefsMarkers from "./atoms/DefsMarkers";
import SatelliteOverlayToggle from "./atoms/SatelliteOverlayToggle";
import LoadingOverlay from "../../atoms/Loading";
import {
@@ -41,6 +44,7 @@ class Map extends React.Component {
this.svgRef = React.createRef();
this.map = null;
this.superclusterIndex = null;
this.tileLayer = null;
this.state = {
mapTransformX: 0,
mapTransformY: 0,
@@ -53,14 +57,22 @@ class Map extends React.Component {
componentDidMount() {
if (this.map === null) {
this.initializeMap();
this.initializeTileLayer();
}
window.dispatchEvent(new Event("resize"));
}
componentDidUpdate(prevProps) {
if (prevProps.ui.tiles !== this.props.ui.tiles && this.map) {
this.initializeTileLayer();
}
}
componentWillReceiveProps(nextProps) {
if (!isIdentical(nextProps.domain.locations, this.props.domain.locations)) {
this.loadClusterData(nextProps.domain.locations);
}
// Set appropriate zoom for narrative
const { bounds } = nextProps.app.map;
if (!isIdentical(bounds, this.props.app.map.bounds) && bounds !== null) {
@@ -92,6 +104,36 @@ class Map extends React.Component {
}
}
initializeTileLayer() {
if (!this.map) {
return;
}
if (
supportedMapboxMap.indexOf(this.props.ui.tiles) !== -1 &&
process.env.MAPBOX_TOKEN &&
process.env.MAPBOX_TOKEN !== defaultToken
) {
this.tileLayer = L.tileLayer(
`http://a.tiles.mapbox.com/v4/mapbox.${this.props.ui.tiles}/{z}/{x}/{y}@2x.png?access_token=${process.env.MAPBOX_TOKEN}`
);
} else if (
process.env.MAPBOX_TOKEN &&
process.env.MAPBOX_TOKEN !== defaultToken
) {
this.tileLayer = L.tileLayer(
`https://api.mapbox.com/styles/v1/${this.props.ui.tiles}/tiles/256/{z}/{x}/{y}@2x?access_token=${process.env.MAPBOX_TOKEN}`
// `http://a.tiles.mapbox.com/styles/v1/${this.props.ui.tiles}/tiles/{z}/{x}/{y}?access_token=${process.env.MAPBOX_TOKEN}`
);
} else {
this.tileLayer = L.tileLayer(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
// "https://api.maptiler.com/maps/bright/256/{z}/{x}/{y}.png?key="
);
}
this.tileLayer.addTo(this.map);
}
initializeMap() {
/**
* Creates a Leaflet map and a tilelayer for the map background
@@ -111,31 +153,7 @@ class Map extends React.Component {
// Initialize supercluster index
this.superclusterIndex = new Supercluster(clusterConfig);
let firstLayer;
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}`
);
} else if (
process.env.MAPBOX_TOKEN &&
process.env.MAPBOX_TOKEN !== defaultToken
) {
firstLayer = L.tileLayer(
`https://api.mapbox.com/styles/v1/${this.props.ui.tiles}/tiles/256/{z}/{x}/{y}@2x?access_token=${process.env.MAPBOX_TOKEN}`
// `http://a.tiles.mapbox.com/styles/v1/${this.props.ui.tiles}/tiles/{z}/{x}/{y}?access_token=${process.env.MAPBOX_TOKEN}`
);
} else {
firstLayer = L.tileLayer(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
// "https://api.maptiler.com/maps/bright/256/{z}/{x}/{y}.png?key="
);
}
firstLayer.addTo(map);
this.initializeTileLayer(map);
map.keyboard.disable();
map.zoomControl.remove();
@@ -517,6 +535,13 @@ class Map extends React.Component {
ui={isFetchingDomain}
language={this.props.app.language}
/>
{this.props.features.USE_SATELLITE_OVERLAY_TOGGLE && (
<SatelliteOverlayToggle
isUsingSatellite={this.props.ui.tiles === "satellite"}
switchToSatellite={this.props.actions.useSatelliteTilesOverlay}
reset={this.props.actions.resetTilesOverlay}
/>
)}
{innerMap}
</div>
);
@@ -548,7 +573,7 @@ function mapStateToProps(state) {
},
},
ui: {
tiles: state.ui.tiles,
tiles: state.ui.tiles.current,
dom: state.ui.dom,
narratives: state.ui.style.narratives,
mapSelectedEvents: state.ui.style.selectedEvents,
@@ -561,4 +586,10 @@ function mapStateToProps(state) {
};
}
export default connect(mapStateToProps)(Map);
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Map);

View File

@@ -0,0 +1,40 @@
import React from "react";
import copy from "../../../../common/data/copy.json";
import { language } from "../../../../common/utilities";
const SatelliteOverlayToggle = ({
switchToSatellite,
reset,
isUsingSatellite,
}) => {
return (
<div id="satellite-overlay-toggle" className="satellite-overlay-toggle">
<button
disabled={!isUsingSatellite}
id="satellite-overlay-toggle-default"
className={
!isUsingSatellite
? "satellite-overlay-toggle-button-active"
: "satellite-overlay-toggle-button-inactive"
}
onClick={reset}
>
{copy[language].tiles.default}
</button>
<button
id="satellite-overlay-toggle-satellite"
className={
isUsingSatellite
? "satellite-overlay-toggle-button-active"
: "satellite-overlay-toggle-button-inactive"
}
disabled={isUsingSatellite}
onClick={switchToSatellite}
>
{copy[language].tiles.satellite}
</button>
</div>
);
};
export default SatelliteOverlayToggle;

View File

@@ -1,9 +1,28 @@
import initial from "../store/initial.js";
import {} from "../actions";
import { USE_SATELLITE_TILES_OVERLAY, RESET_TILES_OVERLAY } from "../actions";
function ui(uiState = initial.ui, action) {
return uiState;
switch (action.type) {
case USE_SATELLITE_TILES_OVERLAY:
return {
...uiState,
tiles: {
...uiState.tiles,
current: "satellite",
},
};
case RESET_TILES_OVERLAY:
return {
...uiState,
tiles: {
...uiState.tiles,
current: uiState.tiles.default,
},
};
default:
return uiState;
}
}
export default ui;

View File

@@ -13,3 +13,4 @@
@import "mediaplayer";
@import "cover";
@import "search";
@import "satelliteoverlaytoggle";

View File

@@ -0,0 +1,28 @@
@import "variables";
.satellite-overlay-toggle {
background-color: rgb(53, 53, 53);
opacity: 0.9;
position: fixed;
top: 4px;
left: 120px;
z-index: $map-overlay;
}
.satellite-overlay-toggle-button-active {
padding: 2px 4px 4px 4px;
border-style: none;
font-size: $small;
font-family: $mainfont;
background-color: rgb(53, 53, 53);
color: white;
}
.satellite-overlay-toggle-button-inactive {
padding: 2px 4px 4px 4px;
border-style: none;
font-size: $small;
font-family: $mainfont;
background-color: rgb(53, 53, 53);
color: rgb(159, 159, 159);
}

View File

@@ -149,7 +149,10 @@ const initial = {
* as well as dom elements to attach SVG
*/
ui: {
tiles: "openstreetmap", // ['openstreetmap', 'streets', 'satellite']
tiles: {
current: "openstreetmap", // ['openstreetmap', 'streets', 'satellite']
default: "openstreetmap", // ['openstreetmap', 'streets', 'satellite']
},
style: {
categories: {
default: global.fallbackEventColor,