{"version":3,"sources":["NoScrollContainer.tsx","Fallback.tsx","MapContainer.tsx","checkWebglSupport.ts","constants.ts","LabelsOverlay.tsx","SpinningCircles.tsx","fullscreen.svg","Button.tsx","Modal.tsx","useKeypress.ts","List.tsx","App.tsx","useWindowSize.ts","reportWebVitals.ts","index.tsx"],"names":["NoScrollContainer","styled","div","children","style","position","width","height","display","alignItems","justifyContent","flexDirection","marginTop","supportsWebGl","canvas","document","createElement","window","WebGLRenderingContext","getContext","e","checkWebglSupport","MapContainer","embed","Fallback","BASE_COLOR","TEXT_COLOR","BACKGROUND_COLOR","SHAPE_LINE_COLOR","SHAPE_FILL_COLOR","colorAsRgba","CIRCLE_LINE_COLOR","CIRCLE_LINE_COLOR__HIGHLIGHTED","hcl","darker","CIRCLE_FILL_COLOR","FALLBACK_COLOR_RGBA","FORMAT_DATE","timeFormat","LIST_RECORD_COLUMNS","name","city","ignore","region","date","role","roleComment","persecutionTypes","typeComment","description","source","opacify","color","v","c","rgb","opacity","toString","col","d3color","console","warn","rgbColor","Math","floor","r","g","b","round","Svg","svg","LabelG","LabelText","text","LabelsOverlay","props","countsData","viewport","sizeScale","ref","useRef","useEffect","current","index","Flatbush","length","textNodes","querySelectorAll","i","getBoundingClientRect","left","top","right","bottom","add","finish","toOmit","Set","has","indices","search","idx","zoom","mercator","WebMercatorViewport","map","d","project","lon","lat","cx","cy","count","scale","max","min","pow","className","transform","y","reverse","SpinningCircles","viewBox","stroke","strokeWidth","fill","fillRule","attributeName","begin","dur","values","calcMode","repeatCount","fillOpacity","defaultProps","undefined","Button","button","Outer","ModalDiv","CloseButton","Modal","key","onKeypress","stopPropagation","maxWidth","maxHeight","onClose","onKeyup","addEventListener","removeEventListener","handleClose","evt","scrollY","body","scrollTo","parseInt","createPortal","onClick","Rows","Column","Row","Name","span","Date","Desc","BadgeArea","Badge","List","selectedCity","listItems","type","ti","href","target","rel","process","REACT_APP_MapboxAccessToken","REACT_APP_StyleUrl","FullscreenButton","a","CenterBlock","TitleArea","LegendBox","Loading","alignSelf","fontSize","TotalCount","Credits","TopLegend","ModalTitle","CityNavButtonsArea","ModalContent","BottomLegend","Absolute","Box","TooltipBox","pointerEvents","padding","textAlign","overflow","fontWeight","CONTROLLER_OPTIONS","MapController","doubleClickZoom","dragRotate","touchRotate","minZoom","maxZoom","INITIAL_VIEWSTATE","bbox","innerWidth","innerHeight","center","longitude","latitude","minPitch","maxPitch","bearing","pitch","altitude","getInitialViewport","MapOuter","flexGrow","MouseMoveContainer","DeckGLOuter","cursor","baseMapOpacity","darkMode","App","useState","setViewport","tooltip","setTooltip","isListOpen","setListOpen","setListItems","setSelectedCity","windowSize","setWindowSize","handleResize","useWindowSize","fetchShapes","useFetch","geoJsonFeatures","useMemo","topology","data","feature","objects","layers","fetchList","formatter","response","parseDate","timeParse","then","csvParse","rawRow","obj","Object","entries","k","csvParseRows","list","sort","descending","recordsByCity","reduce","m","get","Array","set","push","Map","cities","from","keys","fetchLocations","row","locationsByName","loc","maxCount","totalCount","scaleSqrt","range","domain","spatialIndex","x","GeoJsonLayer","id","stroked","filled","lineWidthUnits","getLineWidth","getLineColor","getFillColor","pickable","setTooltipItem","object","dx","dy","virtualReference","ScatterplotLayer","radiusUnits","lineWidthMinPixels","getPosition","getRadius","lineWidthScale","onHover","info","updateTriggers","React","popperElement","setPopperElement","usePopper","styles","attributes","outerRef","isEmbedded","self","err","handleSetSelectedCity","cityItems","onMouseMove","item","found","neighbors","clientX","clientY","onMouseLeave","repeat","controller","onViewStateChange","viewState","views","MapView","ContextProvider","MapContext","Provider","popper","isLoading","title","src","fullscreenIcon","indexOf","next","reportWebVitals","onPerfEntry","Function","getCLS","getFID","getFCP","getLCP","getTTFB","ReactDOM","render","StrictMode","getElementById"],"mappings":"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","file":"static/js/main.b8838695.chunk.js","sourcesContent":["import styled from \"@emotion/styled\";\n\n\nconst NoScrollContainer = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: hidden;\n`;\n\nexport default NoScrollContainer;","import * as React from 'react';\n\nexport default ({ children }: { children: React.ReactChild }) => (\n \n
{children}
\n \n);\n","import React, { ReactNode } from 'react';\nimport NoScrollContainer from './NoScrollContainer';\nimport Fallback from './Fallback';\nimport checkWebglSupport from './checkWebglSupport';\n\ninterface Props {\n embed?: boolean;\n children: ReactNode;\n}\n\nconst supportsWebGl = checkWebglSupport();\n\nconst MapContainer: React.FC = ({ embed, children }) => (\n \n {supportsWebGl ? (\n <>\n {children}\n {/**/}\n {/* */}\n {/**/}\n \n ) : (\n \n Sorry, but your browser doesn't seem to support WebGL which is required for this app.\n \n )}\n \n);\n\nexport default MapContainer;\n","export default function checkWebglSupport() {\n try {\n const canvas = document.createElement('canvas');\n return (\n // @ts-ignore\n !!window.WebGLRenderingContext &&\n !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))\n );\n } catch (e) {\n return false;\n }\n}\n","import {color as d3color, hcl, rgb} from 'd3-color';\nimport {timeFormat} from 'd3-time-format';\n\nexport const BASE_COLOR = '#F04E23';\nexport const TEXT_COLOR = '#2D2D2D';\nexport const BACKGROUND_COLOR = '#DBD9D8';\n\nexport const SHAPE_LINE_COLOR = [150, 100, 100];\nexport const SHAPE_FILL_COLOR = colorAsRgba('#FAEBE5ff');\nexport const CIRCLE_LINE_COLOR = [255, 255, 255];\nexport const CIRCLE_LINE_COLOR__HIGHLIGHTED = colorAsRgba(\n // @ts-ignore\n hcl(BASE_COLOR).darker()\n);\nexport const CIRCLE_FILL_COLOR = colorAsRgba(BASE_COLOR);\nconst FALLBACK_COLOR_RGBA: RGBA = [255, 255, 255, 255];\n\nexport const FORMAT_DATE = timeFormat('%d.%m.%Y');\n\n\nexport const LIST_RECORD_COLUMNS = {\n name: 'Преследуемый',\n city: 'Город',\n ignore: 'Не для карты',\n region: 'Регион',\n date: 'Дата эпизода политпрессинга',\n role: 'Кем является?',\n roleComment: 'Комментарий, если в «Кто является» — «Другое»',\n persecutionTypes: 'Вид политпрессинга',\n typeComment: 'Комментарий к виду политпрессинга',\n description: 'Описание кейса (что произошло)',\n source: 'Ссылка на источник',\n};\n\nexport function opacify(color: string, v: number) {\n const c = rgb(color);\n c.opacity *= v;\n return c.toString();\n}\n\nexport type RGBA = [number, number, number, number];\n\nexport function opacityFloatToInteger(opacity: number): number {\n return Math.round(opacity * 255);\n}\n\nexport function colorAsRgba(color: string): RGBA {\n const col = d3color(color);\n if (!col) {\n console.warn('Invalid color: ', color);\n return FALLBACK_COLOR_RGBA;\n }\n const rgbColor = rgb(color);\n return [Math.floor(rgbColor.r), Math.floor(rgbColor.g), Math.floor(rgbColor.b), opacityFloatToInteger(col.opacity)];\n}\n","import React, {useEffect, useRef} from 'react';\nimport WebMercatorViewport from 'viewport-mercator-project'\nimport {Item} from './App';\nimport {ViewState} from 'react-map-gl';\nimport {ScalePower} from 'd3-scale';\nimport Flatbush from 'flatbush';\nimport styled from '@emotion/styled';\nimport {BASE_COLOR, TEXT_COLOR} from './constants';\n\ninterface Props {\n countsData: Item[] | undefined;\n viewport: ViewState;\n sizeScale: ScalePower | undefined;\n}\n\nconst Svg = styled.svg(`\n position: absolute;\n left:0;top:0;\n width: 100%;height:100%;\n`);\nconst LabelG = styled.g(`\n opacity: 0;\n`);\n\nconst LabelText = styled.text(`\n transition: opacity 0.5s;\n text-anchor: middle;\n alignment-baseline: middle;\n font-size: 10px;\n paint-order: stroke;\n stroke: #fff;\n fill: ${TEXT_COLOR};\n stroke-width: 1px;\n stroke-linecap: butt;\n stroke-linejoin: miter;\n // stroke: #000;\n // font-weight: normal;\n font-weight: bold;\n`);\n\nconst pad = 10;\n\nconst LabelsOverlay: React.FC = (props) => {\n const {countsData, viewport, sizeScale} = props;\n const ref = useRef(null);\n useEffect(() => {\n if (ref.current && countsData) {\n const index = new Flatbush(countsData.length);\n const textNodes = ref.current.querySelectorAll('.label');\n for (let i = 0; i < textNodes.length; i++) {\n const {left, top, right, bottom} = textNodes[i].getBoundingClientRect();\n index.add(left, top, right, bottom);\n }\n index.finish();\n\n const toOmit = new Set();\n // assuming they are sorted by size\n for (let i = textNodes.length - 1; i >= 0 ; i--) {\n if (toOmit.has(i)) continue;\n const textNode = textNodes[i];\n const {left, top, right, bottom} = textNode.getBoundingClientRect();\n const indices = index.search(left - pad, top - pad, right + pad, bottom + pad);\n for (const idx of indices) {\n if (idx !== i) {\n toOmit.add(idx);\n }\n }\n }\n for (let i = 0; i < textNodes.length; i++) {\n // @ts-ignore\n textNodes[i].style.opacity = toOmit.has(i) ? '0' : '1';\n }\n }\n }, [viewport.zoom, ref.current, countsData])\n\n if (!countsData || !sizeScale) return null;\n\n const mercator = new WebMercatorViewport(viewport);\n // @ts-ignore\n const {width,height} = viewport;\n return (\n \n \n {countsData\n .map((d, i) => {\n const [cx, cy] = mercator.project([d.lon, d.lat]);\n const r = sizeScale(d.count);\n const scale = Math.max(1,Math.min(1.5,Math.pow(viewport.zoom,3)*r/300));\n return (\n \n \n {d.name}\n \n \n {d.count}\n \n \n );\n }).reverse()}\n \n \n );\n};\n\nexport default LabelsOverlay;","import React from 'react';\nimport PropTypes from 'prop-types';\nimport {BASE_COLOR} from './constants';\n\n// From https://github.com/ajwann/svg-loaders-react\n\nconst size = 32;\nconst SpinningCircles = ({}: any) => (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n);\n\nSpinningCircles.propTypes = {\n className: PropTypes.string,\n};\n\nSpinningCircles.defaultProps = {\n className: undefined,\n};\n\nexport { SpinningCircles };","export default __webpack_public_path__ + \"static/media/fullscreen.a8019ae3.svg\";","import styled from '@emotion/styled';\nimport {BASE_COLOR} from './constants';\n\n\nconst Button = styled.button`\n cursor: pointer;\n flex-grow: 0;\n display: inline-block;\n padding: 2px 4px;\n opacity: 0.8;\n // transition: opacity 0.2s;\n // &:hover { opacity: 1; }\n border: 1px solid ${BASE_COLOR};\n border-radius: 3px;\n color: ${BASE_COLOR};\n font-size: 0.7rem;\n //font-family: 'Noto Sans', sans-serif;\n margin-bottom: 3px;\n background-color: #fff;\n transition: color 0.2s, background-color 0.2s;\n path {\n transition: fill 0.2s, stroke 0.2s;\n }\n &:hover {\n color: #fff;\n path {\n fill: #fff;\n stroke: #fff;\n }\n background-color: ${BASE_COLOR};\n }\n`;\n\nexport default Button;","import React, {useEffect, useRef} from 'react';\nimport {createPortal} from 'react-dom';\nimport styled from '@emotion/styled';\nimport Button from './Button';\nimport useKeypress from './useKeypress';\nimport {BACKGROUND_COLOR, BASE_COLOR, opacify} from './constants';\n\nexport interface Props {\n width?: string;\n height?: string;\n maxWidth?: string;\n maxHeight?: string;\n onClose: () => void;\n}\n\nconst Outer = styled.div`\n font-size: 0.7rem;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: ${opacify(BACKGROUND_COLOR, 0.85)};\n opacity: 0;\n transition: opacity 0.2s;\n\n &.visible {\n opacity: 1;\n }\n\n display: flex;\n align-items: center;\n justify-items: center;\n justify-content: center;\n z-index: 9999;\n\n h2 {\n font-size: 1.2rem;\n font-weight: bold;\n margin: 0;\n }\n\n h3 {\n font-size: 1rem;\n font-weight: bold;\n margin: 0;\n }\n`;\n\nconst ModalDiv = styled.div`\n position: relative;\n background: #fff;\n border: 1px solid ${opacify(BASE_COLOR, 0.15)};\n box-shadow: 0 0 2px ${opacify(BASE_COLOR, 0.25)};\n border-radius: 5px;\n`;\n\nconst CloseButton = styled(Button)`\n position: absolute;\n right: 10px;\n top: 10px;\n font-size: 12pt;\n border: none;\n z-index: 2;\n`;\n\nconst Modal: React.FC = (props) => {\n const {children,width,height,maxWidth,maxHeight} = props;\n const ref = useRef(null);\n useKeypress('Escape', props.onClose);\n const handleClose = (evt: React.MouseEvent) => {\n evt.stopPropagation();\n props.onClose();\n };\n\n useEffect(() => {\n // https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/\n const {scrollY} = window;\n document.body.style.position = 'fixed';\n document.body.style.width = '100%';\n document.body.style.height = '100%';\n document.body.style.top = `-${scrollY}px`;\n return () => {\n const scrollY = document.body.style.top;\n document.body.style.position = '';\n document.body.style.width = '';\n document.body.style.height = '';\n document.body.style.top = '';\n window.scrollTo(0, parseInt(scrollY || '0') * -1);\n }\n });\n return createPortal(\n \n evt.stopPropagation()}\n style={{\n width,\n height,\n maxWidth,\n maxHeight,\n }}\n >\n \n {children}\n \n ,\n document.body\n );\n};\n\nexport default Modal;\n\n","import { useEffect } from 'react';\n/**\n * useKeyPress\n * @param {string} key - the name of the key to respond to, compared against event.key\n * @param {function} action - the action to perform on key press\n */\nexport default function useKeypress(key: string, onKeypress: () => void, stopPropagation?: boolean) {\n useEffect(() => {\n function onKeyup(e: KeyboardEvent) {\n if (stopPropagation) e.stopPropagation();\n if (e.key === key) onKeypress();\n }\n window.addEventListener('keydown', onKeyup);\n return () => window.removeEventListener('keydown', onKeyup);\n }, []);\n}\n","import React from 'react';\nimport {ListRecord} from './App';\nimport styled from '@emotion/styled';\nimport {BASE_COLOR, FORMAT_DATE, opacify, TEXT_COLOR} from './constants';\n\nconst Outer = styled.div`\n color: ${TEXT_COLOR};\n a { color: ${BASE_COLOR}; }\n padding: 20px;\n`;\n\nconst Rows = styled.div`\n display: flex;\n flex-direction: column;\n &>*+*{ margin-top: 50px; }\n`;\n\nconst Column = styled.div`\n display: flex;\n flex-direction: column;\n &>*+*{ margin-top: 10px; }\n`;\nconst Row = styled.div`\n display: flex;\n flex-direction: row;\n &>*+*{ margin-left: 20px; }\n align-items: center;\n justify-items: center;\n`;\n\nconst Name = styled.span`\n font-weight: bold;\n font-size: 13px;\n`;\n\nconst Date = styled.span`\n font-size: 10px;\n`;\n\nconst Desc = styled.div`\n //font-size: 10px;\n padding: 5px 15px;\n border-left: 2px solid ${BASE_COLOR};\n border-right: 2px solid ${BASE_COLOR};\n background: ${opacify(BASE_COLOR, 0x10/255)};\n`;\n\nconst BadgeArea = styled.div`\n display: flex;\n flex-wrap: wrap;\n &>*+*{ margin-left: 4px; }\n //display: grid;\n //grid-gap: 5px;\n //grid-template-columns: repeat(3, min-content);\n //align-items: flex-start;\n`;\n\nconst Badge = styled.div`\n display: inline-block;\n font-size: 9px;\n background-color: ${opacify(BASE_COLOR, 210/255)};\n color: white;\n border-radius: 4px;\n padding: 2px 5px;\n margin-bottom: 3px;\n`;\n\nexport interface Props {\n selectedCity: string | undefined;\n listItems: ListRecord[] | undefined;\n}\n\nconst List: React.FC = (props) => {\n const {selectedCity, listItems} = props;\n return (\n \n \n {listItems?.map((d,i) =>\n \n \n {d.name}\n {FORMAT_DATE(d.date)}\n \n {d.persecutionTypes &&\n {\n (d.persecutionTypes || d.typeComment).map((type, ti) =>\n {type}\n )\n }}\n {d.role &&
{d.role}
}\n {d.roleComment &&
{d.roleComment}
}\n {d.description && {d.description}}\n {d.source &&\n }\n
\n )}\n
\n
\n );\n};\n\nexport default List;","import styled from '@emotion/styled';\nimport {csvParse, csvParseRows} from 'd3-dsv';\nimport {viewport} from '@mapbox/geo-viewport';\nimport React, {useEffect, useMemo, useRef, useState} from 'react';\nimport './App.css';\nimport useFetch from 'react-fetch-hook';\nimport NoScrollContainer from './NoScrollContainer';\nimport {FeatureCollection} from 'geojson';\nimport MapContainer from './MapContainer';\nimport {DeckGL} from '@deck.gl/react';\nimport {MapController, MapView} from '@deck.gl/core';\nimport {_MapContext as MapContext, StaticMap, ViewState, ViewStateChangeInfo,} from 'react-map-gl';\nimport {GeoJsonLayer, ScatterplotLayer} from '@deck.gl/layers';\nimport {descending, max} from 'd3-array';\nimport {scaleSqrt} from 'd3-scale';\nimport {Topology} from 'topojson-specification';\nimport {feature} from 'topojson-client';\nimport LabelsOverlay from './LabelsOverlay';\nimport {useWindowSize} from './useWindowSize';\nimport Flatbush from 'flatbush';\nimport WebMercatorViewport from 'viewport-mercator-project';\nimport {usePopper} from 'react-popper';\nimport {createPortal} from 'react-dom';\nimport {SpinningCircles} from './SpinningCircles';\nimport fullscreenIcon from './fullscreen.svg';\nimport Modal from './Modal';\nimport List from './List';\nimport {\n BACKGROUND_COLOR,\n BASE_COLOR,\n CIRCLE_FILL_COLOR,\n CIRCLE_LINE_COLOR,\n CIRCLE_LINE_COLOR__HIGHLIGHTED, colorAsRgba,\n LIST_RECORD_COLUMNS,\n opacify,\n SHAPE_FILL_COLOR,\n SHAPE_LINE_COLOR, TEXT_COLOR\n} from './constants';\nimport { timeFormat, timeParse } from 'd3-time-format';\nimport Button from './Button';\n\nconst accessToken = process.env.REACT_APP_MapboxAccessToken;\nconst mapboxMapStyle = process.env.REACT_APP_StyleUrl;\n\n// TODO проекция\n// https://github.com/Kreozot/russian-geo-data/blob/master/map.svg\n\nconst SHOW_BASE_MAP = false;\nconst DARK_MODE = false;\nexport const MIN_ZOOM_LEVEL = 0;\nexport const MAX_ZOOM_LEVEL = 20;\nexport const MIN_PITCH = 0;\nexport const MAX_PITCH = +60;\n\nconst DATA_URL =\n // '/list.csv';\n 'https://jupyter.ovdinfo.org/public/map_navalny_repressions.csv';\nconst CITIES_URL = '/cities.csv';\n\n\nconst Outer = styled(NoScrollContainer)({\n display: 'flex',\n flexDirection: 'column',\n color: TEXT_COLOR,\n});\n\nconst FullscreenButton = styled.a`\n border: 1px solid ${opacify(BASE_COLOR, 0.15)};\n box-shadow: 0 0 2px ${opacify(BASE_COLOR, 0.25)};\n cursor: pointer;\n background: white;\n border-radius: 4px;\n padding: 7px 7px 4px 7px;\n`;\n\nconst CenterBlock = styled.div`\n position: absolute;\n top: 0; left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-items: center;\n justify-content: center;\n`;\n\nconst TitleArea = styled.div`\n display: flex;\n flex-direction: column;\n &>*+* { margin-top: 0.5em; }\n text-align: center;\n & > .title {\n color: ${BASE_COLOR};\n font-weight: bold;\n font-size: 1.2em;\n }\n`;\n\nconst LegendBox = styled.div`\n display: flex;\n flex-direction: column;\n font-size: 0.8rem;\n padding: 10px 15px;\n border-radius: 5px;\n background-color: #fff;\n border: 1px solid ${opacify(BASE_COLOR, 0.15)};\n box-shadow: 0 0 2px ${opacify(BASE_COLOR, 0.25)};\n & a, a:visited {\n color: ${BASE_COLOR};\n }\n`;\n\nconst Loading = styled(LegendBox)({\n display: 'flex',\n alignSelf: 'center',\n fontSize: '1 rem'\n});\n\n\nconst TotalCount = styled.div`\n font-size: 2.5rem;\n font-weight: bold;\n //color: rgb(270, 120, 124);\n color: ${BASE_COLOR};\n //text-shadow: 1px 1px 2px #F04E23,-1px 1px 2px #F04E23,-1px -1px 2px #F04E23,1px -1px 2px #F04E23;\n`;\n\nconst Timestamp = styled.div`\n font-size: 0.6rem;\n height: 1em;\n`;\n\nconst Credits = styled.div`\n font-size: 0.6rem;\n margin-top: 1em;\n line-height: 1.5em;\n`;\n\nconst TopLegend = styled(LegendBox)`\n max-width: 230px;\n right: 20px;\n`;\n\nconst MODAL_TITLE_HEIGHT = 80;\nconst ModalTitle = styled.div`\n box-sizing: border-box;\n padding-left: 20px;\n padding-top: 20px;\n display: flex;\n flex-direction: column;\n &>*+*{ margin-top:10px; }\n height: ${MODAL_TITLE_HEIGHT}px;\n`;\n\nconst CityNavButtonsArea = styled.div`\n display: flex;\n &>*+*{margin-left: 5px;}\n`;\nconst ModalContent = styled.div`\n position: relative;\n width: 100%;\n height: calc(100% - ${MODAL_TITLE_HEIGHT}px);\n overflow: auto;\n`;\n\nconst BottomLegend = styled(LegendBox)`\n color: ${TEXT_COLOR};\n text-align: center;\n max-width: 140px;\n & > *+* { margin-top: 5px; }\n`;\n\nconst getBoxStyle = () => `\n background: rgba(255, 255, 255, 0.9);\n border-radius: 4px;\n font-size: 11px;\n box-shadow: 0 0 5px ${opacify(BASE_COLOR, 0.5)}; \n`;\n\nexport interface AbsoluteProps {\n top?: number;\n left?: number;\n right?: number;\n bottom?: number;\n}\n\n\nexport const Absolute = styled.div(\n ({ top, left, right, bottom }: AbsoluteProps) => `\n position: absolute;\n ${top != null ? `top: ${top}px;` : ''}\n ${left != null ? `left: ${left}px;` : ''}\n ${right != null ? `right: ${right}px;` : ''}\n ${bottom != null ? `bottom: ${bottom}px;` : ''}\n`\n);\n\n\nexport const Box = styled(Absolute)<{}>(getBoxStyle);\n\nconst TooltipBox = styled(Box)({\n pointerEvents: 'none',\n color: TEXT_COLOR,\n padding: 10,\n maxWidth: 120,\n textAlign: 'center',\n display: 'flex',\n flexDirection: 'column',\n overflow: 'hidden',\n '&>.location':{\n // textShadow: `\n // 1px -1px 2px ${TEXT_COLOR},\n // -1px 1px 2px ${TEXT_COLOR},\n // -1px -1px 2px ${TEXT_COLOR},\n // 1px 1px 2px ${TEXT_COLOR}\n // `,\n // color: '#fff'\n fontWeight: 'bold',\n },\n '&>.number':{\n textAlign: 'center',\n fontWeight: 'bold',\n fontSize: '12pt',\n color: BASE_COLOR\n },\n '&>* + *': {\n marginTop: 5,\n },\n});\n\n\nconst CONTROLLER_OPTIONS = {\n type: MapController,\n doubleClickZoom: false,\n dragRotate: false,\n touchRotate: false,\n minZoom: 0,\n maxZoom: 15,\n};\n\n\nfunction getInitialViewport(bbox: [number, number, number, number]) {\n const width = window.innerWidth;\n const height = window.innerHeight;\n const {\n center: [longitude, latitude],\n zoom,\n } = viewport(bbox, [width, height], undefined, undefined, 512, true);\n return {\n width,\n height,\n longitude,\n latitude,\n zoom,\n minZoom: MIN_ZOOM_LEVEL,\n maxZoom: MAX_ZOOM_LEVEL,\n minPitch: MIN_PITCH,\n maxPitch: MAX_PITCH,\n bearing: 0,\n pitch: 0,\n altitude: 1.5,\n };\n}\n\n\nconst INITIAL_VIEWSTATE = getInitialViewport([16.4,41.2,170.0,70]);\n\n\n\nconst MapOuter = styled.div({\n display: 'flex',\n flexGrow: 1,\n position: 'relative',\n});\n\nconst MouseMoveContainer = styled.div`\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0; left: 0;\n`;\n\nconst DeckGLOuter = styled.div<{\n darkMode: boolean;\n baseMapOpacity: number;\n cursor: 'crosshair' | 'pointer' | undefined;\n}>(\n ({ cursor, baseMapOpacity, darkMode }) => `\n #deckgl-wrapper {\n background: ${BACKGROUND_COLOR};\n }\n & #deckgl-overlay {\n // mix-blend-mode: ${darkMode ? 'screen' : 'multiply'};\n }\n & .mapboxgl-map {\n opacity: ${baseMapOpacity}\n }\n ${cursor != null ? `& #deckgl-wrapper { cursor: ${cursor} !important; }` : ''},\n`\n);\n\n\nexport type DateRecord = {\n date: string;\n sheet: string;\n lastUpdated: string;\n latest: string;\n}\n\nexport type Location = {\n name: string;\n lat: number;\n lon: number;\n}\n\nexport type CountItem = {\n name: string;\n count: number;\n}\n\nexport type Item = Location & CountItem;\n\nexport interface ListRecord {\n name: string;\n city: string;\n region: string;\n date: Date;\n role: string;\n roleComment: string;\n persecutionTypes: string[];\n typeComment: string;\n description: string;\n source: string;\n}\n\n\n\nfunction App() {\n const [viewport, setViewport] = useState(INITIAL_VIEWSTATE);\n const [ tooltip, setTooltip] = useState();\n const [isListOpen, setListOpen] = useState(false);\n const [listItems, setListItems] = useState();\n const [selectedCity, setSelectedCity] = useState();\n // const [ hoverItem, setHoverItem ] = useState();\n const handleViewStateChange = ({ viewState }: ViewStateChangeInfo) => {\n setViewport(viewState);\n // setSelectedLocation(null);\n setTooltip(undefined);\n };\n const windowSize = useWindowSize();\n useEffect(() => {\n if (windowSize) // not sure why this doesn't fire from react-map-gl\n setViewport({\n ...viewport,\n ...windowSize,\n });\n },[windowSize?.width, windowSize?.height]);\n const fetchShapes = useFetch(`/shapes.topo.json`);\n const geoJsonFeatures = useMemo(() => {\n const topology = fetchShapes.data as Topology;\n if (topology) {\n return feature(topology, topology.objects['zones']) as any as FeatureCollection;\n }\n return undefined;\n }, [fetchShapes.data]);\n\n const layers: any[] = [];\n const fetchList = useFetch(DATA_URL, {\n formatter: async (response) => {\n const parseDate = timeParse('%m/%e/%Y');\n // (d: string) => {\n // const parts = d.split('/');\n // if (parts.length < 3) return null;\n // return new Date(+parts[2], +parts[0]+1, +parts[1]);\n // }\n const list = await response.text().then((text) =>\n csvParse(text, rawRow => {\n const obj: any = {};\n for (const [k,v] of Object.entries(LIST_RECORD_COLUMNS)) {\n const text = rawRow[v];\n switch (k) {\n case 'persecutionTypes':\n obj[k] = text ? csvParseRows(text)[0] : [];\n break;\n case 'date':\n obj[k] = parseDate(rawRow[LIST_RECORD_COLUMNS.date]!);\n break;\n default:\n obj[k] = text;\n }\n }\n return obj;\n }) as any as ListRecord[]\n );\n list.sort((a,b)=>descending(a.date,b.date))\n return list;\n }\n });\n\n const recordsByCity = useMemo(() => {\n if (!fetchList.data) return undefined;\n return fetchList.data\n .reduce((m, d) => {\n let list = m.get(d.city);\n if (!list) {\n list = new Array();\n m.set(d.city, list);\n }\n list.push(d);\n return m;\n }, new Map>());\n }, [fetchList.data]);\n\n const cities = useMemo(() => {\n if (!recordsByCity) return undefined;\n return Array.from(recordsByCity.keys());\n }, [recordsByCity]);\n\n const fetchLocations = useFetch(CITIES_URL, {\n formatter: (response) =>\n response.text().then((text) =>\n csvParse(text, (row: any) => ({\n name: row['Name'],\n lat: +row['Широта'],\n lon: +row['Долгота'],\n })) as any as Location[]\n ),\n });\n\n const countsData = useMemo(() => {\n if (!recordsByCity || !fetchLocations.data) return undefined;\n const locationsByName = fetchLocations.data\n .reduce((m,d) => {m.set(d.name,d); return m;}, new Map());\n const data: Item[] = [];\n for (const city of recordsByCity.keys()) {\n const loc = locationsByName.get(city);\n if (loc) {\n data.push({\n ...loc,\n count: recordsByCity.get(city)!.length\n });\n } else {\n console.warn(`No location by name '${city}'`)\n }\n }\n data.sort((a,b)=> descending(a.count, b.count));\n return data;\n }, [recordsByCity, fetchLocations.data]);\n\n const maxCount = useMemo(() => {\n if (!countsData) return undefined;\n return max(countsData, d=> d.count)\n }, [countsData]);\n\n const totalCount = useMemo(() => {\n if (!fetchList.data) return undefined;\n return fetchList.data.length;\n }, [fetchList.data]);\n\n const sizeScale = useMemo(() => {\n if (!maxCount) return undefined;\n return scaleSqrt().range([5,20]).domain([1,maxCount]);\n }, [maxCount]);\n\n\n const mercator = useMemo(() => new WebMercatorViewport(viewport), [viewport]);\n\n const spatialIndex = useMemo(() => {\n if (countsData && countsData.length > 0) {\n const index = new Flatbush(countsData.length);\n for (const d of countsData) {\n const [x,y]= mercator.project([d.lon, d.lat]);\n index.add(x,y,x,y);\n }\n index.finish();\n return index;\n }\n return undefined;\n }, [countsData, mercator]);\n\n if (geoJsonFeatures != null) {\n layers.push(\n new GeoJsonLayer({\n id: 'shapes',\n data: geoJsonFeatures,\n stroked: true,\n filled: true,\n opacity: 1.0,\n lineWidthUnits: 'pixels',\n getLineWidth: 0.5,\n getLineColor: SHAPE_LINE_COLOR,\n getFillColor: SHAPE_FILL_COLOR,\n pickable: false,\n }),\n );\n }\n\n const setTooltipItem = (d: Item | undefined) => {\n if (!d || !sizeScale) {\n setTooltip(undefined);\n return;\n }\n if (tooltip?.object === d) return;\n const [x,y]= mercator.project([d.lon, d.lat]);\n const r = sizeScale(d.count);\n // const dx = Math.cos(Math.PI/4) * r + 2;\n // const dy = Math.sin(Math.PI/4) * r + 2;\n const dx = r + 4;\n const dy = r + 4;\n setTooltip({\n object: d,\n x: x + dx,\n y: y + dy,\n virtualReference: {\n getBoundingClientRect() {\n return {\n top: y - dy,\n left: x - dx,\n bottom: y + dy,\n right: x + dx,\n width: dx * 2,\n height: dy * 2,\n };\n }\n },\n }\n );\n };\n\n if (countsData && sizeScale) {\n layers.push(\n new ScatterplotLayer({\n id: 'scatterplot-layer',\n data: countsData,\n pickable: true,\n // opacity: 0.8,\n stroked: true,\n filled: true,\n radiusUnits: 'pixels',\n // radiusMinPixels: 1,\n // radiusMaxPixels: 100,\n lineWidthMinPixels: 1,\n lineWidthUnits: 'pixels',\n getPosition: (d: Item) => [d.lon, d.lat],\n getRadius: (d: Item) => sizeScale(d.count),\n lineWidthScale: 2,\n getLineColor: (d: Item) => {\n if (tooltip && tooltip.object === d) {\n return CIRCLE_LINE_COLOR__HIGHLIGHTED;\n }\n return CIRCLE_LINE_COLOR;\n },\n getLineWidth: (d: Item) => {\n if (tooltip && tooltip.object === d) {\n return 1;\n }\n return 0.25;\n },\n getFillColor: CIRCLE_FILL_COLOR,\n // getFillColor: (d: Item) => {\n // if (tooltip) {\n // if (tooltip.object !== d) {\n // return CIRCLE_FILL_COLOR__MUTED;\n // }\n // }\n // return CIRCLE_FILL_COLOR;\n // },\n // autoHighlight: true,\n // highlightColor: [65, 158, 235],\n onHover: (info: any) => {\n setTooltipItem(info ? info.object : undefined);\n },\n updateTriggers: {\n // getFillColor: [tooltip]\n getLineColor: [tooltip],\n getLineWidth: [tooltip]\n }\n })\n );\n }\n\n const handleMouseMove = (evt: MouseEvent) => {\n let item: Item | undefined = undefined;\n if (spatialIndex && countsData && sizeScale) {\n const found = spatialIndex.neighbors(\n evt.clientX, evt.clientY, 1, 50\n );\n if (found.length > 0) {\n item = countsData[found[0]];\n // setHoverItem(item);\n }\n }\n setTooltipItem(item);\n }\n\n const [popperElement, setPopperElement] = React.useState(null);\n // const [arrowElement, setArrowElement] = useState(null);\n const { styles, attributes } = usePopper(tooltip?.virtualReference, popperElement,\n // { modifiers: [{ name: 'arrow', options: { element: arrowElement } }],}\n );\n\n const outerRef = useRef(null);\n const isEmbedded = useMemo(() => {\n try {\n return window.self !== window.top;\n } catch (err) {}\n return false;\n }, []);\n\n // const [isFullScreen, setFullScreen] = useState(false);\n // const handleFullScreen = () => {\n // const outer = outerRef.current;\n // if (outer) {\n // if (isFullScreen) {\n // // @ts-ignore\n // if (document.exitFullscreen) {\n // document.exitFullscreen().then(() => setFullScreen(false));\n // }\n // } else {\n // if (outer.requestFullscreen) {\n // outer.requestFullscreen().then(() => setFullScreen(true));;\n // }\n // }\n // }\n // };\n\n function handleSetSelectedCity(name: string) {\n if (!recordsByCity) return;\n const cityItems = recordsByCity.get(name);\n if (cityItems) {\n setListOpen(true);\n setListItems(cityItems);\n setSelectedCity(name);\n }\n }\n\n const handleClick = () => {\n if (tooltip && recordsByCity) {\n handleSetSelectedCity(tooltip.object.name);\n }\n };\n\n const handleListClose = () => {\n setListOpen(false);\n setListItems(undefined);\n setSelectedCity(undefined);\n }\n\n const handlePrevCity = () => {\n if (!selectedCity || !cities) return;\n const idx = cities?.indexOf(selectedCity);\n const next = (idx >= 0 ? idx - 1 : cities.length - 1);\n handleSetSelectedCity(cities[next]);\n }\n\n const handleNextCity = () => {\n if (!selectedCity || !cities) return;\n const idx = cities?.indexOf(selectedCity);\n const next = (idx < cities.length - 1 ? idx + 1 : 0);\n handleSetSelectedCity(cities[next]);\n }\n\n const handleShowList = () => {\n if (!cities) return;\n handleSetSelectedCity(cities[0]);\n }\n\n return (\n \n \n \n \n setTooltip(undefined)}\n >\n \n \n {SHOW_BASE_MAP && \n }\n \n \n {tooltip?.object &&\n createPortal(\n
\n {tooltip.object.name}\n
\n
\n {tooltip.object.count}\n
\n
\n Кликните, чтобы увидеть подробный список\n
\n {/*
*/}\n ,\n document.body)\n }\n\n {(fetchList.isLoading || fetchLocations.isLoading)\n ? \n {/*
Загрузка данных…
*/}\n \n
\n : null\n }\n\n \n \n \n
Преследование
\n
сторонников Алексея Навального
\n
с 16.4.2021
\n Показать список\n
\n
\n
\n\n {countsData && totalCount &&\n \n \n
Всего
\n {totalCount}\n
{2<=(totalCount%10) && (totalCount%10)<=4 ? 'человека' : 'человек'}
\n \n Данные: ОВД-Инфо\n \n
\n
\n }\n\n {isEmbedded &&\n \n \n }\n\n \n \n \n\n {recordsByCity && isListOpen &&\n \n \n {selectedCity &&

{selectedCity}

}\n \n ← Предыдущий город\n Следующий город →\n \n
\n \n \n \n }\n \n );\n}\n\nexport default App;\n","import { useState, useEffect } from 'react';\n\n\ninterface Dimensions {\n width: number;\n height: number;\n}\n\nexport function useWindowSize() {\n const [windowSize, setWindowSize] = useState(null);\n\n useEffect(() => {\n function handleResize() {\n setWindowSize({\n width: window.innerWidth,\n height: window.innerHeight,\n });\n }\n\n window.addEventListener(\"resize\", handleResize);\n handleResize();\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n return windowSize;\n}","import { ReportHandler } from 'web-vitals';\n\nconst reportWebVitals = (onPerfEntry?: ReportHandler) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\nimport 'mapbox-gl/dist/mapbox-gl.css';\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n"],"sourceRoot":""}