From 3a54cd7df55b3c44f4026b5d31469a21ee2ec6ee Mon Sep 17 00:00:00 2001 From: Zac Ioannidis Date: Mon, 7 Dec 2020 19:28:07 +0000 Subject: [PATCH] Ingesting config through Create React App --- .babelrc | 3 - .env | 1 + .eslintcache | 2 +- config/env.js | 125 +++++ config/jest/cssTransform.js | 14 + config/jest/fileTransform.js | 40 ++ config/modules.js | 134 ++++++ config/paths.js | 73 +++ config/pnpTs.js | 35 ++ package.json | 124 ++++- scripts/build.js | 212 +++++++++ scripts/start.js | 166 +++++++ scripts/test.js | 53 +++ src/common/utilities.js | 446 +++++++++--------- src/components/CardStack.jsx | 156 +++--- .../presentational/Map/Clusters.jsx | 147 +++--- src/index.jsx | 44 +- webpack.config.js | 84 ---- 18 files changed, 1401 insertions(+), 458 deletions(-) delete mode 100644 .babelrc create mode 100644 .env create mode 100644 config/env.js create mode 100644 config/jest/cssTransform.js create mode 100644 config/jest/fileTransform.js create mode 100644 config/modules.js create mode 100644 config/paths.js create mode 100644 config/pnpTs.js create mode 100644 scripts/build.js create mode 100644 scripts/start.js create mode 100644 scripts/test.js delete mode 100644 webpack.config.js diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 2b7bafa..0000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-env", "@babel/preset-react"] -} diff --git a/.env b/.env new file mode 100644 index 0000000..0e8639b --- /dev/null +++ b/.env @@ -0,0 +1 @@ +FAST_REFRESH=true \ No newline at end of file diff --git a/.eslintcache b/.eslintcache index e92ce81..ec77a40 100644 --- a/.eslintcache +++ b/.eslintcache @@ -1 +1 @@ -[{"/Users/zac/Developer/Forensic Architecture/timemap/src/index.jsx":"1","/Users/zac/Developer/Forensic Architecture/timemap/src/components/App.jsx":"2","/Users/zac/Developer/Forensic Architecture/timemap/src/store/index.js":"3","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Layout.js":"4","/Users/zac/Developer/Forensic Architecture/timemap/src/components/CardStack.jsx":"5","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Map.jsx":"6","/Users/zac/Developer/Forensic Architecture/timemap/src/components/StateOptions.jsx":"7","/Users/zac/Developer/Forensic Architecture/timemap/src/components/InfoPopup.jsx":"8","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Notification.jsx":"9","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Timeline.jsx":"10","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Search.jsx":"11","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Controls.js":"12","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/index.js":"13","/Users/zac/Developer/Forensic Architecture/timemap/src/components/TemplateCover.js":"14","/Users/zac/Developer/Forensic Architecture/timemap/src/components/StaticPage.js":"15","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Popup.js":"16","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Media.js":"17","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Loading.js":"18","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/Layout.js":"19","/Users/zac/Developer/Forensic Architecture/timemap/src/common/global.js":"20","/Users/zac/Developer/Forensic Architecture/timemap/src/common/utilities.js":"21","/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineAxis.jsx":"22","/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineCategories.jsx":"23","/Users/zac/Developer/Forensic Architecture/timemap/src/components/SearchRow.jsx":"24","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Shapes.jsx":"25","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Clusters.jsx":"26","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Sites.jsx":"27","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/DefsMarkers.jsx":"28","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/SelectedEvents.jsx":"29","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Events.jsx":"30","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/ZoomControls.js":"31","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Events.js":"32","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Markers.js":"33","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Handles.js":"34","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/domain.js":"35","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/app.js":"36","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/features.js":"37","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/ui.js":"38","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Clip.js":"39","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Header.js":"40","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Narratives.js":"41","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Adjust.js":"42","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Close.js":"43","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Card.js":"44","/Users/zac/Developer/Forensic Architecture/timemap/src/selectors/index.js":"45","/Users/zac/Developer/Forensic Architecture/timemap/src/actions/index.js":"46","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/ColoredMarkers.jsx":"47","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Controls.js":"48","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Content.js":"49","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/FilterListPanel.js":"50","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/CategoriesListPanel.js":"51","/Users/zac/Developer/Forensic Architecture/timemap/src/store/initial.js":"52","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/BottomActions.js":"53","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/validators.js":"54","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Project.js":"55","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeStar.js":"56","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeBar.js":"57","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeSquare.js":"58","/Users/zac/Developer/Forensic Architecture/timemap/src/common/constants.js":"59","/Users/zac/Developer/Forensic Architecture/timemap/src/selectors/helpers.js":"60","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Spinner.js":"61","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Md.js":"62","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/NoSource.js":"63","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Checkbox.js":"64","/Users/zac/Developer/Forensic Architecture/timemap/src/common/card.js":"65","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/eventSchema.js":"66","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/associationsSchema.js":"67","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/siteSchema.js":"68","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/shapeSchema.js":"69","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/sourceSchema.js":"70","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Sites.js":"71","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Cover.js":"72","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Info.js":"73"},{"size":1321,"mtime":1607358484860,"results":"74","hashOfConfig":"75"},{"size":196,"mtime":1607358484839,"results":"76","hashOfConfig":"75"},{"size":323,"mtime":1607358484871,"results":"77","hashOfConfig":"75"},{"size":13211,"mtime":1607358484842,"results":"78","hashOfConfig":"75"},{"size":4913,"mtime":1607358484840,"results":"79","hashOfConfig":"75"},{"size":15181,"mtime":1607358484842,"results":"80","hashOfConfig":"75"},{"size":629,"mtime":1607358484845,"results":"81","hashOfConfig":"75"},{"size":351,"mtime":1607358484841,"results":"82","hashOfConfig":"75"},{"size":1691,"mtime":1607358484843,"results":"83","hashOfConfig":"75"},{"size":14399,"mtime":1607358484846,"results":"84","hashOfConfig":"75"},{"size":2152,"mtime":1607358484845,"results":"85","hashOfConfig":"75"},{"size":780,"mtime":1607358484857,"results":"86","hashOfConfig":"75"},{"size":234,"mtime":1607358484861,"results":"87","hashOfConfig":"75"},{"size":7243,"mtime":1607358484846,"results":"88","hashOfConfig":"75"},{"size":184,"mtime":1607358484845,"results":"89","hashOfConfig":"75"},{"size":716,"mtime":1607358484857,"results":"90","hashOfConfig":"75"},{"size":4090,"mtime":1607358484843,"results":"91","hashOfConfig":"75"},{"size":589,"mtime":1607358484843,"results":"92","hashOfConfig":"75"},{"size":8383,"mtime":1607358484849,"results":"93","hashOfConfig":"75"},{"size":260,"mtime":1607358484838,"results":"94","hashOfConfig":"75"},{"size":12326,"mtime":1607358484839,"results":"95","hashOfConfig":"75"},{"size":2022,"mtime":1607358484847,"results":"96","hashOfConfig":"75"},{"size":2086,"mtime":1607358484847,"results":"97","hashOfConfig":"75"},{"size":1602,"mtime":1607358484845,"results":"98","hashOfConfig":"75"},{"size":1031,"mtime":1607358484856,"results":"99","hashOfConfig":"75"},{"size":3587,"mtime":1607358484852,"results":"100","hashOfConfig":"75"},{"size":571,"mtime":1607358484856,"results":"101","hashOfConfig":"75"},{"size":498,"mtime":1607358484854,"results":"102","hashOfConfig":"75"},{"size":1142,"mtime":1607358484856,"results":"103","hashOfConfig":"75"},{"size":5058,"mtime":1607358484855,"results":"104","hashOfConfig":"75"},{"size":1215,"mtime":1607358484860,"results":"105","hashOfConfig":"75"},{"size":4685,"mtime":1607358484858,"results":"106","hashOfConfig":"75"},{"size":2479,"mtime":1607358484859,"results":"107","hashOfConfig":"75"},{"size":941,"mtime":1607358484859,"results":"108","hashOfConfig":"75"},{"size":807,"mtime":1607358484861,"results":"109","hashOfConfig":"75"},{"size":8439,"mtime":1607358484860,"results":"110","hashOfConfig":"75"},{"size":154,"mtime":1607358484861,"results":"111","hashOfConfig":"75"},{"size":155,"mtime":1607358484861,"results":"112","hashOfConfig":"75"},{"size":286,"mtime":1607358484857,"results":"113","hashOfConfig":"75"},{"size":580,"mtime":1607358484859,"results":"114","hashOfConfig":"75"},{"size":5135,"mtime":1607358484855,"results":"115","hashOfConfig":"75"},{"size":366,"mtime":1607358484856,"results":"116","hashOfConfig":"75"},{"size":337,"mtime":1607358484856,"results":"117","hashOfConfig":"75"},{"size":1030,"mtime":1607358484856,"results":"118","hashOfConfig":"75"},{"size":9525,"mtime":1607358484871,"results":"119","hashOfConfig":"75"},{"size":8485,"mtime":1607358484836,"results":"120","hashOfConfig":"75"},{"size":1355,"mtime":1607358484854,"results":"121","hashOfConfig":"75"},{"size":793,"mtime":1607358484843,"results":"122","hashOfConfig":"75"},{"size":2326,"mtime":1607358484843,"results":"123","hashOfConfig":"75"},{"size":2840,"mtime":1607358484848,"results":"124","hashOfConfig":"75"},{"size":1009,"mtime":1607358484848,"results":"125","hashOfConfig":"75"},{"size":4935,"mtime":1607358484872,"results":"126","hashOfConfig":"75"},{"size":948,"mtime":1607358484848,"results":"127","hashOfConfig":"75"},{"size":4608,"mtime":1607358484864,"results":"128","hashOfConfig":"75"},{"size":437,"mtime":1607358484860,"results":"129","hashOfConfig":"75"},{"size":377,"mtime":1607358484858,"results":"130","hashOfConfig":"75"},{"size":827,"mtime":1607358484857,"results":"131","hashOfConfig":"75"},{"size":333,"mtime":1607358484858,"results":"132","hashOfConfig":"75"},{"size":106,"mtime":1607358484837,"results":"133","hashOfConfig":"75"},{"size":649,"mtime":1607358484870,"results":"134","hashOfConfig":"75"},{"size":256,"mtime":1607358484857,"results":"135","hashOfConfig":"75"},{"size":1002,"mtime":1607358484843,"results":"136","hashOfConfig":"75"},{"size":398,"mtime":1607358484857,"results":"137","hashOfConfig":"75"},{"size":442,"mtime":1607358484851,"results":"138","hashOfConfig":"75"},{"size":804,"mtime":1607358484837,"results":"139","hashOfConfig":"75"},{"size":1240,"mtime":1607358484862,"results":"140","hashOfConfig":"75"},{"size":252,"mtime":1607358484861,"results":"141","hashOfConfig":"75"},{"size":315,"mtime":1607358484863,"results":"142","hashOfConfig":"75"},{"size":159,"mtime":1607358484862,"results":"143","hashOfConfig":"75"},{"size":498,"mtime":1607358484863,"results":"144","hashOfConfig":"75"},{"size":424,"mtime":1607358484852,"results":"145","hashOfConfig":"75"},{"size":417,"mtime":1607358484851,"results":"146","hashOfConfig":"75"},{"size":417,"mtime":1607358484851,"results":"147","hashOfConfig":"75"},{"filePath":"148","messages":"149","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"nlkfih",{"filePath":"150","messages":"151","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"152","messages":"153","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"154","messages":"155","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"156","messages":"157","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"158","messages":"159","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"160","messages":"161","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"162","messages":"163","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"164","messages":"165","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"166","messages":"167","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"168","messages":"169","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"170","messages":"171","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"172","messages":"173","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"174","messages":"175","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"176","messages":"177","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"178","messages":"179","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"180","messages":"181","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"182","messages":"183","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"184","messages":"185","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"186","messages":"187","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"188","messages":"189","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"190","messages":"191","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"192","messages":"193","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"194","messages":"195","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"196","messages":"197","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"198","messages":"199","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"200","messages":"201","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"202","messages":"203","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"204","messages":"205","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"206","messages":"207","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"208","messages":"209","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"210","messages":"211","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"212","messages":"213","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"214","messages":"215","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"216","messages":"217","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"218","messages":"219","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"220","messages":"221","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"222","messages":"223","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"224","messages":"225","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"226","messages":"227","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"228","messages":"229","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"230","messages":"231","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"232","messages":"233","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"234","messages":"235","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"236","messages":"237","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"238","messages":"239","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"240","messages":"241","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"242","messages":"243","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"244","messages":"245","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"246","messages":"247","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"248","messages":"249","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"250","messages":"251","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"252","messages":"253","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"254","messages":"255","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"256","messages":"257","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"258","messages":"259","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"260","messages":"261","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"262","messages":"263","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"264","messages":"265","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"266","messages":"267","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"268","messages":"269","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"270","messages":"271","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"272","messages":"273","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"274","messages":"275","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"276","messages":"277","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"278","messages":"279","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"280","messages":"281","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"282","messages":"283","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"284","messages":"285","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"286","messages":"287","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"288","messages":"289","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"290","messages":"291","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"292","messages":"293","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/zac/Developer/Forensic Architecture/timemap/src/index.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/App.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/store/index.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Layout.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/CardStack.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Map.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/StateOptions.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/InfoPopup.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Notification.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Timeline.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Search.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Controls.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/index.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/TemplateCover.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/StaticPage.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Popup.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Media.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Loading.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/Layout.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/common/global.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/common/utilities.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineAxis.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineCategories.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/SearchRow.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Shapes.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Clusters.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Sites.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/DefsMarkers.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/SelectedEvents.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Events.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/ZoomControls.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Events.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Markers.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Handles.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/domain.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/app.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/features.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/ui.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Clip.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Header.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Narratives.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Adjust.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Close.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Card.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/selectors/index.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/actions/index.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/ColoredMarkers.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Controls.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Content.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/FilterListPanel.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/CategoriesListPanel.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/store/initial.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/BottomActions.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/validators.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Project.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeStar.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeBar.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeSquare.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/common/constants.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/selectors/helpers.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Spinner.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Md.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/NoSource.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Checkbox.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/common/card.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/eventSchema.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/associationsSchema.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/siteSchema.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/shapeSchema.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/sourceSchema.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Sites.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Cover.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Info.js",[]] \ No newline at end of file +[{"/Users/zac/Developer/Forensic Architecture/timemap/src/index.jsx":"1","/Users/zac/Developer/Forensic Architecture/timemap/src/components/App.jsx":"2","/Users/zac/Developer/Forensic Architecture/timemap/src/store/index.js":"3","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Layout.js":"4","/Users/zac/Developer/Forensic Architecture/timemap/src/components/CardStack.jsx":"5","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Map.jsx":"6","/Users/zac/Developer/Forensic Architecture/timemap/src/components/StateOptions.jsx":"7","/Users/zac/Developer/Forensic Architecture/timemap/src/components/InfoPopup.jsx":"8","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Notification.jsx":"9","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Timeline.jsx":"10","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Search.jsx":"11","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Controls.js":"12","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/index.js":"13","/Users/zac/Developer/Forensic Architecture/timemap/src/components/TemplateCover.js":"14","/Users/zac/Developer/Forensic Architecture/timemap/src/components/StaticPage.js":"15","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Popup.js":"16","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Media.js":"17","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Loading.js":"18","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/Layout.js":"19","/Users/zac/Developer/Forensic Architecture/timemap/src/common/global.js":"20","/Users/zac/Developer/Forensic Architecture/timemap/src/common/utilities.js":"21","/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineAxis.jsx":"22","/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineCategories.jsx":"23","/Users/zac/Developer/Forensic Architecture/timemap/src/components/SearchRow.jsx":"24","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Shapes.jsx":"25","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Clusters.jsx":"26","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Sites.jsx":"27","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/DefsMarkers.jsx":"28","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/SelectedEvents.jsx":"29","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Events.jsx":"30","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/ZoomControls.js":"31","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Events.js":"32","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Markers.js":"33","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Handles.js":"34","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/domain.js":"35","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/app.js":"36","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/features.js":"37","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/ui.js":"38","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Clip.js":"39","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Header.js":"40","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Narratives.js":"41","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Adjust.js":"42","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Close.js":"43","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Card.js":"44","/Users/zac/Developer/Forensic Architecture/timemap/src/selectors/index.js":"45","/Users/zac/Developer/Forensic Architecture/timemap/src/actions/index.js":"46","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/ColoredMarkers.jsx":"47","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Controls.js":"48","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Content.js":"49","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/FilterListPanel.js":"50","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/CategoriesListPanel.js":"51","/Users/zac/Developer/Forensic Architecture/timemap/src/store/initial.js":"52","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/BottomActions.js":"53","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/validators.js":"54","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Project.js":"55","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeStar.js":"56","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeBar.js":"57","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/DatetimeSquare.js":"58","/Users/zac/Developer/Forensic Architecture/timemap/src/common/constants.js":"59","/Users/zac/Developer/Forensic Architecture/timemap/src/selectors/helpers.js":"60","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Spinner.js":"61","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Md.js":"62","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/NoSource.js":"63","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Checkbox.js":"64","/Users/zac/Developer/Forensic Architecture/timemap/src/common/card.js":"65","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/eventSchema.js":"66","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/associationsSchema.js":"67","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/siteSchema.js":"68","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/shapeSchema.js":"69","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/validate/sourceSchema.js":"70","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Sites.js":"71","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Cover.js":"72","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Icons/Info.js":"73"},{"size":1402,"mtime":1607368326591,"results":"74","hashOfConfig":"75"},{"size":196,"mtime":1607358484839,"results":"76","hashOfConfig":"75"},{"size":323,"mtime":1607358484871,"results":"77","hashOfConfig":"75"},{"size":13211,"mtime":1607358484842,"results":"78","hashOfConfig":"75"},{"size":4958,"mtime":1607369161065,"results":"79","hashOfConfig":"75"},{"size":15181,"mtime":1607358484842,"results":"80","hashOfConfig":"75"},{"size":629,"mtime":1607358484845,"results":"81","hashOfConfig":"75"},{"size":351,"mtime":1607358484841,"results":"82","hashOfConfig":"75"},{"size":1691,"mtime":1607358484843,"results":"83","hashOfConfig":"75"},{"size":14399,"mtime":1607358484846,"results":"84","hashOfConfig":"75"},{"size":2152,"mtime":1607358484845,"results":"85","hashOfConfig":"75"},{"size":780,"mtime":1607358484857,"results":"86","hashOfConfig":"75"},{"size":234,"mtime":1607358484861,"results":"87","hashOfConfig":"75"},{"size":7243,"mtime":1607358484846,"results":"88","hashOfConfig":"75"},{"size":184,"mtime":1607358484845,"results":"89","hashOfConfig":"75"},{"size":716,"mtime":1607358484857,"results":"90","hashOfConfig":"75"},{"size":4090,"mtime":1607358484843,"results":"91","hashOfConfig":"75"},{"size":589,"mtime":1607358484843,"results":"92","hashOfConfig":"75"},{"size":8383,"mtime":1607358484849,"results":"93","hashOfConfig":"75"},{"size":260,"mtime":1607358484838,"results":"94","hashOfConfig":"75"},{"size":12622,"mtime":1607368454582,"results":"95","hashOfConfig":"75"},{"size":2022,"mtime":1607358484847,"results":"96","hashOfConfig":"75"},{"size":2086,"mtime":1607358484847,"results":"97","hashOfConfig":"75"},{"size":1602,"mtime":1607358484845,"results":"98","hashOfConfig":"75"},{"size":1031,"mtime":1607358484856,"results":"99","hashOfConfig":"75"},{"size":3796,"mtime":1607368294386,"results":"100","hashOfConfig":"75"},{"size":571,"mtime":1607358484856,"results":"101","hashOfConfig":"75"},{"size":498,"mtime":1607358484854,"results":"102","hashOfConfig":"75"},{"size":1142,"mtime":1607358484856,"results":"103","hashOfConfig":"75"},{"size":5058,"mtime":1607358484855,"results":"104","hashOfConfig":"75"},{"size":1215,"mtime":1607358484860,"results":"105","hashOfConfig":"75"},{"size":4685,"mtime":1607358484858,"results":"106","hashOfConfig":"75"},{"size":2479,"mtime":1607358484859,"results":"107","hashOfConfig":"75"},{"size":941,"mtime":1607358484859,"results":"108","hashOfConfig":"75"},{"size":807,"mtime":1607358484861,"results":"109","hashOfConfig":"75"},{"size":8439,"mtime":1607358484860,"results":"110","hashOfConfig":"75"},{"size":154,"mtime":1607358484861,"results":"111","hashOfConfig":"75"},{"size":155,"mtime":1607358484861,"results":"112","hashOfConfig":"75"},{"size":286,"mtime":1607358484857,"results":"113","hashOfConfig":"75"},{"size":580,"mtime":1607358484859,"results":"114","hashOfConfig":"75"},{"size":5135,"mtime":1607358484855,"results":"115","hashOfConfig":"75"},{"size":366,"mtime":1607358484856,"results":"116","hashOfConfig":"75"},{"size":337,"mtime":1607358484856,"results":"117","hashOfConfig":"75"},{"size":1030,"mtime":1607358484856,"results":"118","hashOfConfig":"75"},{"size":9525,"mtime":1607358484871,"results":"119","hashOfConfig":"75"},{"size":8485,"mtime":1607358484836,"results":"120","hashOfConfig":"75"},{"size":1355,"mtime":1607358484854,"results":"121","hashOfConfig":"75"},{"size":793,"mtime":1607358484843,"results":"122","hashOfConfig":"75"},{"size":2326,"mtime":1607358484843,"results":"123","hashOfConfig":"75"},{"size":2840,"mtime":1607358484848,"results":"124","hashOfConfig":"75"},{"size":1009,"mtime":1607358484848,"results":"125","hashOfConfig":"75"},{"size":4935,"mtime":1607358484872,"results":"126","hashOfConfig":"75"},{"size":948,"mtime":1607358484848,"results":"127","hashOfConfig":"75"},{"size":4608,"mtime":1607358484864,"results":"128","hashOfConfig":"75"},{"size":437,"mtime":1607358484860,"results":"129","hashOfConfig":"75"},{"size":377,"mtime":1607358484858,"results":"130","hashOfConfig":"75"},{"size":827,"mtime":1607358484857,"results":"131","hashOfConfig":"75"},{"size":333,"mtime":1607358484858,"results":"132","hashOfConfig":"75"},{"size":106,"mtime":1607358484837,"results":"133","hashOfConfig":"75"},{"size":649,"mtime":1607358484870,"results":"134","hashOfConfig":"75"},{"size":256,"mtime":1607358484857,"results":"135","hashOfConfig":"75"},{"size":1002,"mtime":1607358484843,"results":"136","hashOfConfig":"75"},{"size":398,"mtime":1607358484857,"results":"137","hashOfConfig":"75"},{"size":442,"mtime":1607358484851,"results":"138","hashOfConfig":"75"},{"size":804,"mtime":1607358484837,"results":"139","hashOfConfig":"75"},{"size":1240,"mtime":1607358484862,"results":"140","hashOfConfig":"75"},{"size":252,"mtime":1607358484861,"results":"141","hashOfConfig":"75"},{"size":315,"mtime":1607358484863,"results":"142","hashOfConfig":"75"},{"size":159,"mtime":1607358484862,"results":"143","hashOfConfig":"75"},{"size":498,"mtime":1607358484863,"results":"144","hashOfConfig":"75"},{"size":424,"mtime":1607358484852,"results":"145","hashOfConfig":"75"},{"size":417,"mtime":1607358484851,"results":"146","hashOfConfig":"75"},{"size":417,"mtime":1607358484851,"results":"147","hashOfConfig":"75"},{"filePath":"148","messages":"149","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},"1mdei7r",{"filePath":"151","messages":"152","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"153","messages":"154","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"155","messages":"156","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"157","usedDeprecatedRules":"150"},{"filePath":"158","messages":"159","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"160","messages":"161","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"162","usedDeprecatedRules":"150"},{"filePath":"163","messages":"164","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"165","usedDeprecatedRules":"150"},{"filePath":"166","messages":"167","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"168","usedDeprecatedRules":"150"},{"filePath":"169","messages":"170","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"171","messages":"172","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"173","messages":"174","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"175","messages":"176","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"177","usedDeprecatedRules":"150"},{"filePath":"178","messages":"179","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"180","messages":"181","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"182","usedDeprecatedRules":"150"},{"filePath":"183","messages":"184","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"185","usedDeprecatedRules":"150"},{"filePath":"186","messages":"187","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"188","usedDeprecatedRules":"150"},{"filePath":"189","messages":"190","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"191","usedDeprecatedRules":"150"},{"filePath":"192","messages":"193","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"194","messages":"195","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"196","messages":"197","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"198","usedDeprecatedRules":"150"},{"filePath":"199","messages":"200","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"201","usedDeprecatedRules":"150"},{"filePath":"202","messages":"203","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"204","messages":"205","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"206","messages":"207","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"208","messages":"209","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"210","messages":"211","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"212","messages":"213","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"214","messages":"215","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"216","messages":"217","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"218","messages":"219","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"220","messages":"221","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"222","messages":"223","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"224","messages":"225","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"226","messages":"227","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"228","messages":"229","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"230","messages":"231","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"232","messages":"233","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"234","messages":"235","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"236","messages":"237","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"238","messages":"239","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"240","messages":"241","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"242","messages":"243","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"244","usedDeprecatedRules":"150"},{"filePath":"245","messages":"246","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"247","usedDeprecatedRules":"150"},{"filePath":"248","messages":"249","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"250","messages":"251","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"252","messages":"253","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"254","usedDeprecatedRules":"150"},{"filePath":"255","messages":"256","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"257","messages":"258","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"259","usedDeprecatedRules":"150"},{"filePath":"260","messages":"261","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"262","usedDeprecatedRules":"150"},{"filePath":"263","messages":"264","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"265","messages":"266","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"267","usedDeprecatedRules":"150"},{"filePath":"268","messages":"269","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"270","messages":"271","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"272","messages":"273","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"274","messages":"275","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"276","usedDeprecatedRules":"150"},{"filePath":"277","messages":"278","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"279","usedDeprecatedRules":"150"},{"filePath":"280","messages":"281","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"282","usedDeprecatedRules":"150"},{"filePath":"283","messages":"284","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"285","usedDeprecatedRules":"150"},{"filePath":"286","messages":"287","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"288","messages":"289","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"290","messages":"291","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"292","messages":"293","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"294","usedDeprecatedRules":"150"},{"filePath":"295","messages":"296","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"297","messages":"298","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"299","usedDeprecatedRules":"150"},{"filePath":"300","messages":"301","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"302","usedDeprecatedRules":"150"},{"filePath":"303","messages":"304","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"305","messages":"306","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"307","messages":"308","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"309","messages":"310","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"311","messages":"312","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"313","messages":"314","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"315","messages":"316","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},{"filePath":"317","messages":"318","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"150"},"/Users/zac/Developer/Forensic Architecture/timemap/src/index.jsx",[],["319","320"],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/App.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/store/index.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Layout.js",["321","322"],"/* global alert, Event */\nimport React from 'react'\n\nimport { bindActionCreators } from 'redux'\nimport { connect } from 'react-redux'\nimport * as actions from '../actions'\nimport * as selectors from '../selectors'\n\nimport MediaOverlay from './Overlay/Media'\nimport LoadingOverlay from './Overlay/Loading'\nimport Map from './Map.jsx'\nimport Toolbar from './Toolbar/Layout'\nimport CardStack from './CardStack.jsx'\n// import {CardStack} from '@forensic-architecture/design-system'\nimport NarrativeControls from './presentational/Narrative/Controls.js'\nimport InfoPopup from './InfoPopup.jsx'\nimport Popup from './presentational/Popup'\nimport Timeline from './Timeline.jsx'\nimport Notification from './Notification.jsx'\nimport StateOptions from './StateOptions.jsx'\nimport StaticPage from './StaticPage'\nimport TemplateCover from './TemplateCover'\n\nimport colors from '../common/global'\nimport { binarySearch, insetSourceFrom } from '../common/utilities'\nimport { isMobileOnly } from 'react-device-detect'\nimport Search from './Search.jsx'\n\nclass Dashboard extends React.Component {\n constructor (props) {\n super(props)\n\n this.handleViewSource = this.handleViewSource.bind(this)\n this.handleHighlight = this.handleHighlight.bind(this)\n this.setNarrative = this.setNarrative.bind(this)\n this.setNarrativeFromFilters = this.setNarrativeFromFilters.bind(this)\n this.handleSelect = this.handleSelect.bind(this)\n this.getCategoryColor = this.getCategoryColor.bind(this)\n this.findEventIdx = this.findEventIdx.bind(this)\n this.onKeyDown = this.onKeyDown.bind(this)\n this.selectNarrativeStep = this.selectNarrativeStep.bind(this)\n }\n\n componentDidMount () {\n if (!this.props.app.isMobile) {\n this.props.actions.fetchDomain()\n .then(domain =>\n this.props.actions.updateDomain({\n domain,\n features: this.props.features\n }))\n }\n // NOTE: hack to get the timeline to always show. Not entirely sure why\n // this is necessary.\n window.dispatchEvent(new Event('resize'))\n }\n\n handleHighlight (highlighted) {\n this.props.actions.updateHighlighted((highlighted) || null)\n }\n\n handleViewSource (source) {\n this.props.actions.updateSource(source)\n }\n\n findEventIdx (theEvent) {\n const { events } = this.props.domain\n return binarySearch(\n events,\n theEvent,\n (theev, otherev) => {\n return theev.datetime - otherev.datetime\n }\n )\n }\n\n handleSelect (selected, axis) {\n const matchedEvents = []\n const TIMELINE_AXIS = 0\n if (axis === TIMELINE_AXIS) {\n matchedEvents.push(selected)\n // find in events\n const { events } = this.props.domain\n const idx = this.findEventIdx(selected)\n // check events before\n let ptr = idx - 1\n\n while (\n ptr >= 0 &&\n (events[idx].datetime).getTime() === (events[ptr].datetime).getTime()\n ) {\n if (events[ptr].id !== selected.id) {\n matchedEvents.push(events[ptr])\n }\n ptr -= 1\n }\n // check events after\n ptr = idx + 1\n\n while (\n ptr < events.length &&\n (events[idx].datetime).getTime() === (events[ptr].datetime).getTime()\n ) {\n if (events[ptr].id !== selected.id) {\n matchedEvents.push(events[ptr])\n }\n ptr += 1\n }\n } else { // Map..\n const std = { ...selected }\n delete std.sources\n Object.values(std).forEach(ev => matchedEvents.push(ev))\n }\n this.props.actions.updateSelected(matchedEvents)\n }\n\n getCategoryColor (category) {\n if (!this.props.features.USE_CATEGORIES) { return colors.fallbackEventColor }\n\n const cat = this.props.ui.style.categories[category]\n if (cat) {\n return cat\n } else {\n return this.props.ui.style.categories['default']\n }\n }\n\n setNarrative (narrative) {\n // only handleSelect if narrative is not null and has associated events\n if (narrative && narrative.steps.length >= 1) {\n this.handleSelect([ narrative.steps[0] ])\n }\n this.props.actions.updateNarrative(narrative)\n }\n\n setNarrativeFromFilters (withSteps) {\n const { app, domain } = this.props\n let activeFilters = app.associations.filters\n\n if (activeFilters.length === 0) {\n alert('No filters selected, cant narrativise')\n return\n }\n\n activeFilters = activeFilters.map(f => ({ name: f }))\n\n const evs = domain.events.filter(ev => {\n let hasOne = false\n // add event if it has at least one matching filter\n for (let i = 0; i < activeFilters.length; i++) {\n if (ev.associations.includes(activeFilters[i].name)) {\n hasOne = true\n break\n }\n }\n if (hasOne) return true\n return false\n })\n\n if (evs.length === 0) {\n alert('No associated events, cant narrativise')\n return\n }\n\n const name = activeFilters.map(f => f.name).join('-')\n const desc = activeFilters.map(f => f.description).join('\\n\\n')\n this.setNarrative({\n id: name,\n label: name,\n description: desc,\n withLines: withSteps,\n steps: evs.map(insetSourceFrom(domain.sources))\n })\n }\n\n selectNarrativeStep (idx) {\n // Try to find idx if event passed rather than number\n if (typeof idx !== 'number') {\n let e = idx[0] || idx\n\n if (this.props.app.associations.narrative) {\n const { steps } = this.props.app.associations.narrative\n // choose the first event at a given location\n const locationEventId = e.id\n const narrativeIdxObj = steps.find(s => s.id === locationEventId)\n let narrativeIdx = steps.indexOf(narrativeIdxObj)\n\n if (narrativeIdx > -1) {\n idx = narrativeIdx\n }\n }\n }\n\n const { narrative } = this.props.app.associations\n if (narrative === null) return\n\n if (idx < narrative.steps.length && idx >= 0) {\n const step = narrative.steps[idx]\n\n this.handleSelect([step])\n this.props.actions.updateNarrativeStepIdx(idx)\n }\n }\n\n onKeyDown (e) {\n const { narrative, selected } = this.props.app\n const { events } = this.props.domain\n\n const prev = idx => {\n if (narrative === null) {\n this.handleSelect(events[idx - 1], 0)\n } else {\n this.selectNarrativeStep(this.props.narrativeIdx - 1)\n }\n }\n const next = idx => {\n if (narrative === null) {\n this.handleSelect(events[idx + 1], 0)\n } else {\n this.selectNarrativeStep(this.props.narrativeIdx + 1)\n }\n }\n if (selected.length > 0) {\n const ev = selected[selected.length - 1]\n const idx = this.findEventIdx(ev)\n switch (e.keyCode) {\n case 37: // left arrow\n case 38: // up arrow\n if (idx <= 0) return\n prev(idx)\n break\n case 39: // right arrow\n case 40: // down arrow\n if (idx < 0 || idx >= this.props.domain.length - 1) return\n next(idx)\n break\n default:\n }\n }\n }\n\n renderIntroPopup (isMobile, styles) {\n const { app, actions } = this.props\n\n const extraContent = isMobile ?
\n

This platform is not suitable for mobile.

Please re-visit the site on a device with a larger screen.

\n
: null\n\n return \n {extraContent}\n \n }\n\n render () {\n const { actions, app, domain, features } = this.props\n const dateHeight = 80\n const padding = 2\n const checkMobile = (isMobileOnly || window.innerWidth < 600)\n\n const popupStyles = {\n height: checkMobile ? '100vh' : 'fit-content',\n display: checkMobile ? 'block' : 'table',\n width: checkMobile ? '100vw' : window.innerWidth > 768 ? '60vw' : `calc(100vw - var(--toolbar-width))`,\n maxWidth: checkMobile ? '100vw' : 600,\n maxHeight: checkMobile ? '100vh' : window.innerHeight > 768 ? `calc(100vh - ${app.timeline.dimensions.height}px - ${dateHeight}px)` : `100vh`,\n left: checkMobile ? padding : 'var(--toolbar-width)',\n top: 0,\n overflowY: 'scroll'\n }\n\n if (checkMobile) {\n const msg = 'This platform is not suitable for mobile. Please re-visit the site on a device with a larger screen.'\n return (\n
\n {(features.USE_COVER && !app.intro) && (\n \n {/* enable USE_COVER in config.js features, and customise your header */}\n {/* pass 'actions.toggleCover' as a prop to your custom header */}\n {\n /* eslint-disable no-undef */\n alert(msg)\n /* eslint-enable no-undef */\n }} />\n \n )}\n {app.intro && <>\n {this.renderIntroPopup(true, popupStyles)}\n }\n {!app.intro && !features.USE_COVER && (\n
{msg}
\n )}\n
\n )\n }\n\n return (\n
\n actions.toggleAssociations('filters', filters),\n onCategoryFilter: categories => actions.toggleAssociations('categories', categories),\n onSelectNarrative: this.setNarrative\n }}\n />\n this.handleSelect(ev, 1)\n }}\n />\n this.handleSelect(ev, 0),\n onUpdateTimerange: actions.updateTimeRange,\n getCategoryColor: this.getCategoryColor\n }}\n />\n null}\n onHighlight={this.handleHighlight}\n onToggleCardstack={() => actions.updateSelected([])}\n getCategoryColor={this.getCategoryColor}\n />\n 0}\n timelineDims={app.timeline.dimensions}\n onClickHandler={this.setNarrativeFromFilters}\n />\n this.selectNarrativeStep(this.props.narrativeIdx + 1),\n onPrev: () => this.selectNarrativeStep(this.props.narrativeIdx - 1),\n onSelectNarrative: this.setNarrative\n }}\n />\n \n {this.renderIntroPopup(false, popupStyles)}\n {app.debug ? : null}\n {features.USE_SEARCH && ()}\n {app.source ? (\n {\n actions.updateSource(null)\n }\n }\n />\n ) : null}\n \n {features.USE_COVER && (\n \n {/* enable USE_COVER in config.js features, and customise your header */}\n {/* pass 'actions.toggleCover' as a prop to your custom header */}\n \n \n )}\n
\n )\n }\n}\n\nfunction mapDispatchToProps (dispatch) {\n return {\n actions: bindActionCreators(actions, dispatch)\n }\n}\n\nexport default connect(\n state => ({\n ...state,\n narrativeIdx: selectors.selectNarrativeIdx(state),\n narratives: selectors.selectNarratives(state),\n selected: selectors.selectSelected(state)\n }),\n mapDispatchToProps\n)(Dashboard)\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/CardStack.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Map.jsx",["323"],"/* global L, Event */\nimport React from 'react'\nimport { Portal } from 'react-portal'\nimport Supercluster from 'supercluster'\n\nimport { connect } from 'react-redux'\nimport * as selectors from '../selectors'\n\nimport 'leaflet'\n\nimport Sites from './presentational/Map/Sites.jsx'\nimport Shapes from './presentational/Map/Shapes.jsx'\nimport Events from './presentational/Map/Events.jsx'\nimport Clusters from './presentational/Map/Clusters.jsx'\nimport SelectedEvents from './presentational/Map/SelectedEvents.jsx'\nimport Narratives from './presentational/Map/Narratives'\nimport DefsMarkers from './presentational/Map/DefsMarkers.jsx'\nimport LoadingOverlay from '../components/Overlay/Loading'\n\nimport { mapClustersToLocations, isIdentical, isLatitude, isLongitude, calculateTotalClusterPoints, calcClusterSize } from '../common/utilities'\n\n// NB: important constants for map, TODO: make statics\nconst supportedMapboxMap = ['streets', 'satellite']\nconst defaultToken = 'your_token'\n\nclass Map extends React.Component {\n constructor () {\n super()\n this.projectPoint = this.projectPoint.bind(this)\n this.onClusterSelect = this.onClusterSelect.bind(this)\n this.loadClusterData = this.loadClusterData.bind(this)\n this.getClusterChildren = this.getClusterChildren.bind(this)\n this.svgRef = React.createRef()\n this.map = null\n this.superclusterIndex = null\n this.state = {\n mapTransformX: 0,\n mapTransformY: 0,\n indexLoaded: false,\n clusters: []\n }\n this.styleLocation = this.styleLocation.bind(this)\n }\n\n componentDidMount () {\n if (this.map === null) {\n this.initializeMap()\n }\n window.dispatchEvent(new Event('resize'))\n }\n\n componentWillReceiveProps (nextProps) {\n if (!isIdentical(nextProps.domain.locations, this.props.domain.locations)) {\n this.loadClusterData(nextProps.domain.locations)\n }\n // Set appropriate zoom for narrative\n const { bounds } = nextProps.app.map\n if (!isIdentical(bounds, this.props.app.map.bounds) &&\n bounds !== null) {\n this.map.fitBounds(bounds)\n } else {\n if (!isIdentical(nextProps.app.selected, this.props.app.selected)) {\n // Fly to first of events selected\n const eventPoint = (nextProps.app.selected.length > 0) ? nextProps.app.selected[0] : null\n\n if (eventPoint !== null && eventPoint.latitude && eventPoint.longitude) {\n // this.map.setView([eventPoint.latitude, eventPoint.longitude])\n this.map.setView([eventPoint.latitude, eventPoint.longitude], this.map.getZoom(), {\n 'animate': true,\n 'pan': {\n 'duration': 0.7\n }\n })\n }\n }\n }\n }\n\n initializeMap () {\n /**\n * Creates a Leaflet map and a tilelayer for the map background\n */\n const { map: mapConfig, cluster: clusterConfig } = this.props.app\n\n const map =\n L.map(this.props.ui.dom.map)\n .setView(mapConfig.anchor, mapConfig.startZoom)\n .setMinZoom(mapConfig.minZoom)\n .setMaxZoom(mapConfig.maxZoom)\n .setMaxBounds(mapConfig.maxBounds)\n\n // Initialize supercluster index\n this.superclusterIndex = new Supercluster(clusterConfig)\n\n let firstLayer\n\n if ((supportedMapboxMap.indexOf(this.props.ui.tiles) !== -1) && process.env.MAPBOX_TOKEN && process.env.MAPBOX_TOKEN !== defaultToken) {\n firstLayer = L.tileLayer(\n `http://a.tiles.mapbox.com/v4/mapbox.${this.props.ui.tiles}/{z}/{x}/{y}@2x.png?access_token=${process.env.MAPBOX_TOKEN}`\n )\n } else if (process.env.MAPBOX_TOKEN && process.env.MAPBOX_TOKEN !== defaultToken) {\n firstLayer = L.tileLayer(\n `http://a.tiles.mapbox.com/styles/v1/${this.props.ui.tiles}/tiles/{z}/{x}/{y}?access_token=${process.env.MAPBOX_TOKEN}`\n )\n } else {\n firstLayer = L.tileLayer(\n 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'\n )\n }\n firstLayer.addTo(map)\n\n map.keyboard.disable()\n map.zoomControl.remove()\n\n map.on('moveend', () => {\n this.updateClusters()\n this.alignLayers()\n })\n\n map.on('move zoomend viewreset', () => this.alignLayers())\n map.on('zoomstart', () => { if (this.svgRef.current !== null) this.svgRef.current.classList.add('hide') })\n map.on('zoomend', () => { if (this.svgRef.current !== null) this.svgRef.current.classList.remove('hide') })\n window.addEventListener('resize', () => { this.alignLayers() })\n\n this.map = map\n }\n\n getMapDetails () {\n const bounds = this.map.getBounds()\n const bbox = [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()]\n const zoom = this.map.getZoom()\n return [bbox, zoom]\n }\n\n updateClusters () {\n const [bbox, zoom] = this.getMapDetails()\n if (this.superclusterIndex && this.state.indexLoaded) {\n this.setState({\n clusters: this.superclusterIndex.getClusters(bbox, zoom)\n })\n }\n }\n\n loadClusterData (locations) {\n if (locations && locations.length > 0 && this.superclusterIndex) {\n const convertedLocations = locations.reduce((acc, loc) => {\n const { longitude, latitude } = loc\n const validCoordinates = isLatitude(latitude) && isLongitude(longitude)\n if (validCoordinates) {\n const feature = {\n type: 'Feature',\n properties: {\n cluster: false,\n id: loc.label\n },\n geometry: {\n type: 'Point',\n coordinates: [longitude, latitude]\n }\n }\n acc.push(feature)\n }\n return acc\n }, [])\n this.superclusterIndex.load(convertedLocations)\n this.setState({ indexLoaded: true }, () => {\n this.updateClusters()\n })\n } else {\n this.setState({ clusters: [] })\n }\n }\n\n getClusterChildren (clusterId) {\n if (this.superclusterIndex) {\n try {\n const children = this.superclusterIndex.getLeaves(clusterId, Infinity, 0)\n return mapClustersToLocations(children, this.props.domain.locations)\n } catch (err) {\n return []\n }\n }\n return []\n }\n\n getSelectedClusters () {\n const { selected } = this.props.app\n const selectedIds = selected.map(sl => sl.id)\n\n if (this.state.clusters && this.state.clusters.length > 0) {\n return this.state.clusters.reduce((acc, cl) => {\n if (cl.properties.cluster) {\n const children = this.getClusterChildren(cl.properties.cluster_id)\n if (children && children.length > 0) {\n children.forEach(child => {\n const clusterPresent = acc.findIndex(item => item.id === cl.id) >= 0\n if (selectedIds.includes(child.id) && !clusterPresent) {\n acc.push(cl)\n }\n })\n }\n }\n return acc\n }, [])\n }\n return []\n }\n\n alignLayers () {\n const mapNode = document.querySelector('.leaflet-map-pane')\n if (mapNode === null) return { transformX: 0, transformY: 0 }\n\n // We'll get the transform of the leaflet container,\n // which will let us offset the SVG by the same quantity\n const transform = window\n .getComputedStyle(mapNode)\n .getPropertyValue('transform')\n\n // Offset with leaflet map transform boundaries\n this.setState({\n mapTransformX: +transform.split(',')[4],\n mapTransformY: +transform.split(',')[5].split(')')[0]\n })\n }\n\n projectPoint (location) {\n const latLng = new L.LatLng(location[0], location[1])\n return {\n x: this.map.latLngToLayerPoint(latLng).x + this.state.mapTransformX,\n y: this.map.latLngToLayerPoint(latLng).y + this.state.mapTransformY\n }\n }\n\n onClusterSelect ({ id, latitude, longitude }) {\n const expansionZoom = Math.max(this.superclusterIndex.getClusterExpansionZoom(parseInt(id)), this.superclusterIndex.options.minZoom)\n const zoomLevelsToSkip = 2\n const zoomToFly = Math.max(expansionZoom + zoomLevelsToSkip, this.props.app.cluster.maxZoom)\n this.map.flyTo(new L.LatLng(latitude, longitude), zoomToFly)\n }\n\n getClientDims () {\n const boundingClient = document.querySelector(`#${this.props.ui.dom.map}`).getBoundingClientRect()\n\n return {\n width: boundingClient.width,\n height: boundingClient.height\n }\n }\n\n renderTiles () {\n const pane = this.map.getPanes().overlayPane\n const { width, height } = this.getClientDims()\n\n return this.map ? (\n \n \n \n ) : null\n }\n\n renderSites () {\n return (\n \n )\n }\n\n renderShapes () {\n return (\n \n )\n }\n\n renderNarratives () {\n const hasNarratives = this.props.domain.narratives.length > 0\n return (\n \n )\n }\n\n /**\n * Determines additional styles on the for each location.\n * A location consists of an array of events (see selectors). The function\n * also has full access to the domain and redux state to derive values if\n * necessary. The function should return an array, where the value at the\n * first index is a styles object for the SVG at the location, and the value\n * at the second index is an optional additional component that renders in\n * the div.\n */\n styleLocation (location) {\n return [null, null]\n }\n\n styleCluster (cluster) {\n return [null, null]\n }\n\n renderEvents () {\n /*\n Uncomment below to filter out the locations already present in a cluster.\n Leaving these lines commented out renders all the locations on the map, regardless of whether or not they are clustered\n */\n\n const individualClusters = this.state.clusters.filter(cl => !cl.properties.cluster)\n const filteredLocations = mapClustersToLocations(individualClusters, this.props.domain.locations)\n return (\n \n )\n }\n\n renderClusters () {\n const allClusters = this.state.clusters.filter(cl => cl.properties.cluster)\n return (\n \n )\n }\n\n renderSelected () {\n const selectedClusters = this.getSelectedClusters()\n const totalMarkers = []\n\n this.props.app.selected.forEach(s => {\n const { latitude, longitude } = s\n totalMarkers.push({\n latitude,\n longitude,\n radius: this.props.ui.eventRadius\n })\n })\n\n const totalClusterPoints = calculateTotalClusterPoints(this.state.clusters)\n\n selectedClusters.forEach(cl => {\n if (cl.properties.cluster) {\n const { coordinates } = cl.geometry\n totalMarkers.push({\n latitude: String(coordinates[1]),\n longitude: String(coordinates[0]),\n radius: calcClusterSize(cl.properties.point_count, totalClusterPoints)\n })\n }\n })\n\n return (\n \n )\n }\n\n renderMarkers () {\n return (\n \n \n \n )\n }\n\n render () {\n const { isShowingSites, isFetchingDomain } = this.props.app.flags\n const classes = this.props.app.narrative ? 'map-wrapper narrative-mode' : 'map-wrapper'\n const innerMap = this.map ? (\n \n {this.renderTiles()}\n {this.renderMarkers()}\n {isShowingSites ? this.renderSites() : null}\n {this.renderShapes()}\n {this.renderNarratives()}\n {this.renderEvents()}\n {this.renderClusters()}\n {this.renderSelected()}\n \n ) : null\n\n return (\n
\n
\n \n {innerMap}\n
\n )\n }\n}\n\nfunction mapStateToProps (state) {\n return {\n domain: {\n locations: selectors.selectLocations(state),\n narratives: selectors.selectNarratives(state),\n categories: selectors.getCategories(state),\n sites: selectors.selectSites(state),\n shapes: selectors.selectShapes(state)\n },\n app: {\n views: state.app.associations.views,\n selected: selectors.selectSelected(state),\n highlighted: state.app.highlighted,\n map: state.app.map,\n cluster: state.app.cluster,\n language: state.app.language,\n loading: state.app.loading,\n narrative: state.app.associations.narrative,\n coloringSet: state.app.associations.coloringSet,\n flags: {\n isShowingSites: state.app.flags.isShowingSites,\n isFetchingDomain: state.app.flags.isFetchingDomain\n }\n },\n ui: {\n tiles: state.ui.tiles,\n dom: state.ui.dom,\n narratives: state.ui.style.narratives,\n mapSelectedEvents: state.ui.style.selectedEvents,\n shapes: state.ui.style.shapes,\n eventRadius: state.ui.eventRadius,\n radial: state.ui.style.clusters.radial,\n filterColors: state.ui.coloring.colors\n },\n features: selectors.getFeatures(state)\n }\n}\n\nexport default connect(mapStateToProps)(Map)\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/StateOptions.jsx",["324"],"import React, { useState } from 'react'\n\nexport default ({ showing, onClickHandler, timelineDims }) => {\n if (!showing) {\n return null\n }\n\n const [checked, setChecked] = useState(false)\n const handleCheck = () => setChecked(!checked)\n const onNarrativise = () => onClickHandler(checked)\n\n return
\n
\n
Narrativise
\n \n \n
\n
\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/InfoPopup.jsx",["325"],"import React from 'react'\nimport Popup from './presentational/Popup'\nimport copy from '../common/data/copy.json'\n\nexport default ({ isOpen, onClose, language, styles }) => (\n \n)\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Notification.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Timeline.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Search.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Controls.js",["326"],"import React from 'react'\nimport Card from './Card'\nimport Adjust from './Adjust'\nimport Close from './Close'\n\nexport default ({ narrative, methods }) => {\n if (!narrative) return null\n\n const { current, steps } = narrative\n const prevExists = current !== 0\n const nextExists = current < steps.length - 1\n\n return (\n \n \n \n \n methods.onSelectNarrative(null)}\n closeMsg='-- exit from narrative --'\n />\n \n )\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/index.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/TemplateCover.js",["327","328"],"import React from 'react'\nimport { connect } from 'react-redux'\nimport { Player } from 'video-react'\nimport marked from 'marked'\nimport MediaOverlay from './Overlay/Media'\nimport falogo from '../assets/fa-logo.png'\nimport bcatlogo from '../assets/bellingcat-logo.png'\nconst MEDIA_HIDDEN = -2\n\n/**\n * Manages the presentation of props that come in from the store's app.cover.\n * These are documented in docs/custom-cover.md.\n * The component is a bit of a mess, keeping a lot of internal state and using\n * a couple of weird offset calculations... but it works for the time being.\n */\nclass TemplateCover extends React.Component {\n constructor (props) {\n super(props)\n this.state = {\n video: MEDIA_HIDDEN,\n featureLang: 0\n }\n }\n\n getVideo (index, headerEndIndex) {\n if (index < headerEndIndex) {\n return this.props.cover.headerVideos[index]\n } else if (index >= 0) {\n return this.props.cover.videos[index - headerEndIndex]\n } else {\n return null\n }\n }\n\n onVideoClickHandler (index) {\n const buffer = this.props.cover.headerVideos ? this.props.cover.headerVideos.length : 0\n return () => {\n this.setState({\n video: index + buffer\n })\n }\n }\n\n renderFeature () {\n const { featureVideo } = this.props.cover\n const { featureLang } = this.state\n const { translations } = featureVideo\n const source = featureLang === 0\n ? featureVideo\n : {\n ...translations[featureLang - 1],\n poster: featureVideo.poster\n }\n\n return (\n
\n
\n {translations && translations.map((trans, idx) => {\n const langIdx = idx + 1 // default lang idx is 0\n if (featureLang !== langIdx) {\n return
this.setState({ featureLang: langIdx })} className='trans-button'>{trans.code}
\n } else {\n return
this.setState({ featureLang: 0 })} className='trans-button'>ENG
\n }\n })}\n
\n\n \n
\n )\n }\n\n renderHeaderVideos () {\n const { headerVideos } = this.props.cover\n return (\n
\n { headerVideos.slice(0, 2).map((media, index) => (\n
this.setState({ video: index })}>\n {media.buttonTitle}\n
\n )) }\n
\n )\n }\n\n renderButton (button, yellow) {\n return (\n \n )\n }\n\n renderMediaOverlay () {\n const video = this.getVideo(this.state.video, this.props.cover.headerVideos ? this.props.cover.headerVideos.length : 0)\n return (\n this.setState({ video: MEDIA_HIDDEN })}\n />\n )\n }\n\n render () {\n if (!this.props.cover) {\n return (\n
\n You haven't specified any cover props. Put them in the values that overwrite the store in app.cover\n
\n )\n }\n\n const { videos, footerButton } = this.props.cover\n const { showing } = this.props\n return (\n
\n
\n \n \n \n \n \n \n
\n
\n {\n this.props.cover.bgVideo ? (\n
\n \n \n \n
\n ) : null\n }\n

\n {\n this.props.cover.subtitle ? (\n

{this.props.cover.subtitle}

\n ) : null\n }\n {\n this.props.cover.subsubtitle ? (\n
{this.props.cover.subsubtitle}
\n ) : null\n }\n\n {this.props.cover.featureVideo ? this.renderFeature() : null}\n
\n {this.props.cover.headerVideos ? this.renderHeaderVideos() : null}\n {this.props.cover.headerButton ? this.renderButton(this.props.cover.headerButton) : null}\n
\n
\n {this.props.cover.exploreButton}\n
\n
\n
\n\n {Array.isArray(this.props.cover.description)\n ? this.props.cover.description.map(e =>
)\n :
}\n\n {videos ? (\n
\n
\n {/* NOTE: only take first four videos, drop any others for style reasons */}\n { videos && videos.slice(0, 2).map((media, index) => (\n
\n {media.buttonTitle}
{media.buttonSubtitle}\n
\n )) }\n
\n
\n { videos.length > 2 && this.props.cover.videos.slice(2, 4).map((media, index) => (\n
\n {media.buttonTitle}
{media.buttonSubtitle}\n
\n )) }\n
\n
\n ) : null}\n {footerButton ? (\n
\n
\n {this.renderButton(footerButton)}\n
\n
\n ) : null}\n
\n\n {\n this.state.video !== MEDIA_HIDDEN ? this.renderMediaOverlay() : null }\n
\n )\n }\n}\n\nfunction mapStateToProps (state) {\n return {\n cover: state.app.cover\n }\n}\n\nexport default connect(mapStateToProps)(TemplateCover)\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/StaticPage.js",["329"],"import React from 'react'\n\nexport default ({ showing, children }) => {\n return (\n
\n {children}\n
\n )\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Popup.js",["330"],"import React from 'react'\nimport marked from 'marked'\n\nconst fontSize = window.innerWidth > 1000 ? 14 : 18\n\nexport default ({\n content = [],\n styles = {},\n isOpen = true,\n onClose,\n title,\n theme = 'light',\n isMobile = false,\n children\n}) => (\n
\n
\n
\n \n

{title}

\n
\n {content.map(t =>
)}\n {children}\n
\n
\n)\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Media.js",["331"],"import React from 'react'\nimport marked from 'marked'\nimport Content from './Content'\nimport Controls from './Controls'\nimport { selectTypeFromPathWithPoster } from '../../common/utilities'\n\n/*\n * Inside the SourceOverlay, both the currently displaying media and language\n * can be changed by the user. These are both managed in this component's React\n * state.\n */\nclass SourceOverlay extends React.Component {\n constructor () {\n super()\n this.state = { mediaIdx: 0, langIdx: 0 }\n this.onShiftGallery = this.onShiftGallery.bind(this)\n }\n\n getTypeCounts (media) {\n return media.reduce(\n (acc, vl) => {\n acc[vl.type] += 1\n return acc\n },\n { Image: 0, Video: 0, Text: 0 }\n )\n }\n\n onShiftGallery (shift) {\n // no more left\n if (this.state.mediaIdx === 0 && shift === -1) return\n // no more right\n if (this.state.mediaIdx === this.props.source.paths.length - 1 && shift === 1) return\n this.setState({ mediaIdx: this.state.mediaIdx + shift })\n }\n\n switchLanguage (idx) {\n this.setState({ langIdx: idx })\n }\n\n renderContent (source) {\n const { url, title, paths, date, type, poster, description } = source\n const shortenedTitle = title.substring(0, 100)\n return (\n \n
\n
\n close\n
\n\n

{shortenedTitle}

\n\n
\n
e.stopPropagation()}>\n
\n this.switchLanguage(lang)}\n translations={this.props.translations}\n langIdx={this.state.langIdx}\n media={paths.map(p => selectTypeFromPathWithPoster(p, poster))}\n viewIdx={this.state.mediaIdx}\n />\n
\n
\n\n
\n \n\n
\n {description ?
\n
\n
: null}\n\n {(type || date || url) ? (\n
\n
\n {type ?

Evidence type

: null}\n {type ?

perm_media{type}

: null}\n
\n
\n {date ?

Date Published

: null}\n {date ?

today{date}

: null}\n
\n
\n {url ?

Link

: null}\n {url ? linkLink to original URL : null}\n
\n
\n ) : null}\n
\n
\n \n )\n }\n\n renderIntlContent () {\n const { langIdx } = this.state\n const { translations, source } = this.props\n let translated = null\n if (translations && translations.length && langIdx > 0) {\n translated = translations[langIdx - 1]\n }\n if (translated) {\n translated = {\n ...translated,\n poster: source.poster,\n // NOTE: this is to allow a slightly nicer syntax when using the Media\n // overlay in cover videos.\n paths: translated.file ? [translated.file] : translated.paths\n }\n }\n\n return this.renderContent(langIdx === 0 ? source : translated)\n }\n\n render () {\n if (typeof (this.props.source) !== 'object') {\n return this.renderError()\n }\n\n return (\n
\n {this.renderIntlContent()}\n
\n )\n }\n}\n\nexport default SourceOverlay\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Loading.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Toolbar/Layout.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/common/global.js",["332"],"export const colors = {\n fa_red: '#eb443e',\n yellow: '#ffd800',\n black: '#000',\n white: '#fff'\n}\n\nexport default {\n fallbackEventColor: colors.fa_red,\n darkBackground: colors.black,\n primaryHighlight: colors.fa_red,\n secondaryHighlight: colors.white\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/common/utilities.js",["333"],"import moment from \"moment\";\nimport hash from \"object-hash\";\n\nlet { DATE_FMT, TIME_FMT } = process.env;\nif (!DATE_FMT) DATE_FMT = \"MM/DD/YYYY\";\nif (!TIME_FMT) TIME_FMT = \"HH:mm\";\n\nconsole.log(process.env);\nexport const language = process.env.store.app.language || \"en-US\";\n\nexport function calcDatetime(date, time) {\n if (!time) time = \"00:00\";\n const dt = moment(`${date} ${time}`, `${DATE_FMT} ${TIME_FMT}`);\n return dt.toDate();\n}\n\nexport function getCoordinatesForPercent(radius, percent) {\n const x = radius * Math.cos(2 * Math.PI * percent);\n const y = radius * Math.sin(2 * Math.PI * percent);\n return [x, y];\n}\n\n/**\n * This function takes the array of percentages: [0.5, 0.5, ...]\n * and maps it by index to the set of colors ['#fff', '#000', ...]\n * If there aren't enough colors in the set, it raises an error for the user\n *\n * Return value:\n * ex. {'#fff': 0.5, '#000': 0.5, ...} */\nexport function zipColorsToPercentages(colors, percentages) {\n if (colors.length < percentages.length)\n throw new Error(\"You must declare an appropriate number of filter colors\");\n\n return percentages.reduce((map, percent, idx) => {\n map[colors[idx]] = percent;\n return map;\n }, {});\n}\n\n/**\n * Get URI params to start with predefined set of\n * https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript\n * @param {string} name: name of paramater to search\n * @param {string} url: url passed as variable, defaults to window.location.href\n */\nexport function getParameterByName(name, url) {\n if (!url) url = window.location.href;\n name = name.replace(/[[\\]]/g, `\\\\$&`);\n\n const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`);\n const results = regex.exec(url);\n\n if (!results) return null;\n if (!results[2]) return \"\";\n\n return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n}\n\n/**\n * Compare two arrays of scalars\n * @param {array} arr1: array of numbers\n * @param {array} arr2: array of numbers\n */\nexport function areEqual(arr1, arr2) {\n return (\n arr1.length === arr2.length &&\n arr1.every((element, index) => {\n return element === arr2[index];\n })\n );\n}\n\n/**\n * Return whether the variable is neither null nor undefined\n * @param {object} variable\n */\nexport function isNotNullNorUndefined(variable) {\n return typeof variable !== \"undefined\" && variable !== null;\n}\n\n/*\n * Taken from: https://stackoverflow.com/questions/1026069/how-do-i-make-the-first-letter-of-a-string-uppercase-in-javascript\n */\nexport function capitalize(string) {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function trimAndEllipse(string, stringNum) {\n if (string.length > stringNum) {\n return string.substring(0, 120) + \"...\";\n }\n return string;\n}\n\n/**\n * From the set of associations, grab a given filter's set of parents,\n * ie. all the elements in the path array before the idx where the filter is located.\n * If we can't find the filter by the ID, we know its a meta filter, so we look\n * through every association's given path attribute to find its location.\n *\n * Returns the list of parents: ex. ['Chemical', 'Tear Gas', ...]\n */\nexport function getFilterParents(associations, filter) {\n for (let a of associations) {\n const { filter_paths: fp } = a;\n if (a.id === filter) {\n return fp.slice(0, fp.length - 1);\n }\n const filterIndex = fp.indexOf(filter);\n if (filterIndex === 0) return [];\n if (filterIndex > 0) return fp.slice(0, filterIndex);\n }\n throw new Error(\"Attempted to get parents of nonexistent filter\");\n}\n\n/**\n * Grabs the second to last element in the paths array for a given existing filter.\n * This is the filter's most immediate ancestor.\n */\nexport function getImmediateFilterParent(associations, filter) {\n const parents = getFilterParents(associations, filter);\n if (parents.length === 0) return null;\n return parents[parents.length - 1];\n}\n\n/**\n * Grab a meta filter's siblings, by way of the the `filter_path` hierarcy.\n */\nexport function getMetaFilterSiblings(allFilters, filterParent, filterKey) {\n const idxParent = allFilters\n .map((f) => {\n return f.filter_paths.reduceRight((acc, path, idx) => {\n if (path === filterParent) return f.filter_paths[idx + 1];\n return acc;\n }, null);\n })\n .filter((metaFilter) => !!metaFilter && metaFilter !== filterKey);\n return [...new Set(idxParent)];\n}\n\n/**\n * Grabs a given filter's siblings: the set of associations that share the same immediate filter parent.\n */\nexport function getFilterSiblings(allFilters, filterParent, filterKey) {\n const isMetaFilter = !allFilters.map((filt) => filt.id).includes(filterKey);\n\n if (isMetaFilter) {\n return getMetaFilterSiblings(allFilters, filterParent, filterKey);\n }\n\n return allFilters.reduce((acc, val) => {\n const valParent = getImmediateFilterParent(allFilters, val.id);\n if (valParent === filterParent && val.id !== filterKey) acc.push(val.id);\n return acc;\n }, []);\n}\n\nexport function getEventCategories(event, categories) {\n const matchedCategories = [];\n if (event.associations && event.associations.length > 0) {\n event.associations.reduce((acc, val) => {\n const foundCategory = categories.find((cat) => cat.id === val);\n if (foundCategory) acc.push(foundCategory);\n return acc;\n }, matchedCategories);\n }\n return matchedCategories;\n}\n\n/**\n * Inset the full source represenation from 'allSources' into an event. The\n * function is 'curried' to allow easy use with maps. To use for a single\n * source, call with two sets of parentheses:\n * const src = insetSourceFrom(sources)(anEvent)\n */\nexport function insetSourceFrom(allSources) {\n return (event) => {\n let sources;\n if (!event.sources) {\n sources = [];\n } else {\n sources = event.sources.map((id) => {\n return allSources.hasOwnProperty(id) ? allSources[id] : null;\n });\n }\n return {\n ...event,\n sources,\n };\n };\n}\n\n/**\n * Debugging function: put in place of a mapStateToProps function to\n * view that source modal by default\n */\nexport function injectSource(id) {\n return (state) => {\n return {\n ...state,\n app: {\n ...state.app,\n source: state.domain.sources[id],\n },\n };\n };\n}\n\nexport function urlFromEnv(ext) {\n if (process.env[ext]) {\n if (!Array.isArray(process.env[ext])) {\n return [`${process.env.SERVER_ROOT}${process.env[ext]}`];\n } else {\n return process.env[ext].map(\n (suffix) => `${process.env.SERVER_ROOT}${suffix}`\n );\n }\n } else {\n return null;\n }\n}\n\nexport function toggleFlagAC(flag) {\n return (appState) => ({\n ...appState,\n flags: {\n ...appState.flags,\n [flag]: !appState.flags[flag],\n },\n });\n}\n\nexport function selectTypeFromPath(path) {\n let type;\n switch (true) {\n case /\\.(png|jpg)$/.test(path):\n type = \"Image\";\n break;\n case /\\.(mp4)$/.test(path):\n type = \"Video\";\n break;\n case /\\.(md)$/.test(path):\n type = \"Text\";\n break;\n default:\n type = \"Unknown\";\n break;\n }\n return { type, path };\n}\n\nexport function typeForPath(path) {\n let type;\n path = path.trim();\n switch (true) {\n case /\\.((png)|(jpg)|(jpeg))$/.test(path):\n type = \"Image\";\n break;\n case /\\.(mp4)$/.test(path):\n type = \"Video\";\n break;\n case /\\.(md)$/.test(path):\n type = \"Text\";\n break;\n case /\\.(pdf)$/.test(path):\n type = \"Document\";\n break;\n default:\n type = \"Unknown\";\n break;\n }\n return type;\n}\n\nexport function selectTypeFromPathWithPoster(path, poster) {\n return { type: typeForPath(path), path, poster };\n}\n\nexport function isIdentical(obj1, obj2) {\n return hash(obj1) === hash(obj2);\n}\n\nexport function calcOpacity(num) {\n /* Events have opacity 0.5 by default, and get added to according to how many\n * other events there are in the same render. The idea here is that the\n * overlaying of events builds up a 'heat map' of the event space, where\n * darker areas represent more events with proportion */\n const base = num >= 1 ? 0.9 : 0;\n return base + Math.min(0.5, 0.08 * (num - 1));\n}\n\nexport function calcClusterOpacity(pointCount, totalPoints) {\n /* Clusters represent multiple events within a specific radius. The darker the cluster,\n the larger the number of underlying events. We use a multiplication factor (50) here as well\n to ensure that the larger clusters have an appropriately darker shading. */\n return Math.min(0.85, 0.08 + (pointCount / totalPoints) * 50);\n}\n\nexport function calcClusterSize(pointCount, totalPoints) {\n /* The larger the cluster size, the higher the count of points that the cluster represents.\n Just like with opacity, we use a multiplication factor to ensure that clusters with higher point\n counts appear larger. */\n const maxSize = totalPoints > 60 ? 40 : 20;\n return Math.min(maxSize, 10 + (pointCount / totalPoints) * 150);\n}\n\nexport function calculateTotalClusterPoints(clusters) {\n return clusters.reduce((total, cl) => {\n if (cl && cl.properties && cl.properties.cluster) {\n total += cl.properties.point_count;\n }\n return total;\n }, 0);\n}\n\nexport function isLatitude(lat) {\n return !!lat && isFinite(lat) && Math.abs(lat) <= 90;\n}\n\nexport function isLongitude(lng) {\n return !!lng && isFinite(lng) && Math.abs(lng) <= 180;\n}\n\nexport function mapClustersToLocations(clusters, locations) {\n return clusters.reduce((acc, cl) => {\n const foundLocation = locations.find(\n (location) => location.label === cl.properties.id\n );\n if (foundLocation) acc.push(foundLocation);\n return acc;\n }, []);\n}\n\n/**\n * Loops through a set of either locations or events\n * and calculates the proportionate percentage of every given association in relation to the coloring set\n */\nexport function calculateColorPercentages(set, coloringSet) {\n if (coloringSet.length === 0) return [1];\n const associationMap = {};\n\n for (const [idx, value] of coloringSet.entries()) {\n for (let filter of value) {\n associationMap[filter] = idx;\n }\n }\n\n const associationCounts = new Array(coloringSet.length);\n associationCounts.fill(0);\n\n let totalAssociations = 0;\n\n set.forEach((item) => {\n let innerSet = \"events\" in item ? item.events : item;\n\n if (!Array.isArray(innerSet)) innerSet = [innerSet];\n\n innerSet.forEach((val) => {\n val.associations.forEach((a) => {\n const idx = associationMap[a];\n if (!idx && idx !== 0) return;\n associationCounts[idx] += 1;\n totalAssociations += 1;\n });\n });\n });\n\n if (totalAssociations === 0) return [1];\n\n return associationCounts.map((count) => count / totalAssociations);\n}\n\n/**\n * Gets the idx of a given filter in relation to its position in the coloring set\n *\n * Example coloringSet = [['Chemical', 'Tear Gas'], ['Procedural', 'Destruction of property']]\n */\nexport function getFilterIdxFromColorSet(filter, coloringSet) {\n let filterIdx = -1;\n coloringSet.map((set, idx) => {\n const foundIdx = set.indexOf(filter);\n if (foundIdx !== -1) filterIdx = idx;\n });\n return filterIdx;\n}\n\nexport const dateMin = function () {\n return Array.prototype.slice.call(arguments).reduce(function (a, b) {\n return a < b ? a : b;\n });\n};\n\nexport const dateMax = function () {\n return Array.prototype.slice.call(arguments).reduce(function (a, b) {\n return a > b ? a : b;\n });\n};\n\n/** Taken from\n * https://stackoverflow.com/questions/22697936/binary-search-in-javascript\n * **/\nexport function binarySearch(ar, el, compareFn) {\n var m = 0;\n var n = ar.length - 1;\n while (m <= n) {\n var k = (n + m) >> 1;\n var cmp = compareFn(el, ar[k]);\n if (cmp > 0) {\n m = k + 1;\n } else if (cmp < 0) {\n n = k - 1;\n } else {\n return k;\n }\n }\n return -m - 1;\n}\n\nexport function makeNiceDate(datetime) {\n if (datetime === null) return null;\n // see https://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date\n const dateTimeFormat = new Intl.DateTimeFormat(language, {\n year: \"numeric\",\n month: \"long\",\n day: \"2-digit\",\n });\n const [\n { value: month },\n ,\n { value: day },\n ,\n { value: year },\n ] = dateTimeFormat.formatToParts(datetime);\n\n return `${day} ${month}, ${year}`;\n}\n\n/**\n * Sets the default locale for d3 to format dates in each available language.\n * @param {Object} d3 - An instance of D3\n */\nexport function setD3Locale(d3) {\n const languages = {\n \"es-MX\": require(\"./data/es-MX.json\"),\n };\n\n if (language !== \"es-US\" && languages[language]) {\n d3.timeFormatDefaultLocale(languages[language]);\n }\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineAxis.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/TimelineCategories.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/SearchRow.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Shapes.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Clusters.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Sites.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/DefsMarkers.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/SelectedEvents.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Events.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/ZoomControls.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Events.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Markers.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Handles.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/domain.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/app.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/features.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/reducers/ui.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Clip.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Timeline/Header.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/Narratives.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Adjust.js",["334"],"import React from 'react'\n\nexport default ({ isDisabled, direction, onClickHandler }) => {\n return (\n \n \n {`chevron_${direction}`}\n \n
\n )\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Close.js",["335"],"import React from 'react'\n\nexport default ({ onClickHandler, closeMsg }) => {\n return (\n \n \n \n \n
{closeMsg}
\n
\n )\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Narrative/Card.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/selectors/index.js",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/actions/index.js",["336","337"],"/* global fetch, alert */\nimport { urlFromEnv } from '../common/utilities'\n\n// TODO: relegate these URLs entirely to environment variables\n// const CONFIG_URL = urlFromEnv('CONFIG_EXT')\nconst EVENT_DATA_URL = urlFromEnv('EVENTS_EXT')\nconst ASSOCIATIONS_URL = urlFromEnv('ASSOCIATIONS_EXT')\nconst SOURCES_URL = urlFromEnv('SOURCES_EXT')\nconst SITES_URL = urlFromEnv('SITES_EXT')\nconst SHAPES_URL = urlFromEnv('SHAPES_EXT')\n\nconst domainMsg = (domainType) => `Something went wrong fetching ${domainType}. Check the URL or try disabling them in the config file.`\n\nexport function fetchDomain () {\n let notifications = []\n\n function handleError (message) {\n notifications.push({\n message,\n type: 'error'\n })\n return []\n }\n\n return (dispatch, getState) => {\n const features = getState().features\n dispatch(toggleFetchingDomain())\n\n // let configPromise = Promise.resolve([])\n // if (features.USE_REMOTE_CONFIG) {\n // configPromise = fetch(CONFIG_URL)\n // .then(response => response.json())\n // .catch(() => handleError(\"Couldn't find data at the config URL you specified.\"))\n // }\n\n // NB: EVENT_DATA_URL is a list, and so results are aggregated\n const eventPromise = Promise.all(\n EVENT_DATA_URL.map(url => fetch(url)\n .then(response => response.json())\n .catch(() => handleError('events'))\n )\n ).then(results => results.flatMap(t => t))\n\n let associationsPromise = Promise.resolve([])\n if (features.USE_ASSOCIATIONS) {\n if (!ASSOCIATIONS_URL) {\n associationsPromise = Promise.resolve(handleError('USE_ASSOCIATIONS is true, but you have not provided a ASSOCIATIONS_EXT'))\n } else {\n associationsPromise = fetch(ASSOCIATIONS_URL)\n .then(response => response.json())\n .catch(() => handleError(domainMsg('associations')))\n }\n }\n\n let sourcesPromise = Promise.resolve([])\n if (features.USE_SOURCES) {\n if (!SOURCES_URL) {\n sourcesPromise = Promise.resolve(handleError('USE_SOURCES is true, but you have not provided a SOURCES_EXT'))\n } else {\n sourcesPromise = fetch(SOURCES_URL)\n .then(response => response.json())\n .catch(() => handleError(domainMsg('sources')))\n }\n }\n\n let sitesPromise = Promise.resolve([])\n if (features.USE_SITES) {\n sitesPromise = fetch(SITES_URL)\n .then(response => response.json())\n .catch(() => handleError(domainMsg('sites')))\n }\n\n let shapesPromise = Promise.resolve([])\n if (features.USE_SHAPES) {\n shapesPromise = fetch(SHAPES_URL)\n .then(response => response.json())\n .catch(() => handleError(domainMsg('shapes')))\n }\n\n return Promise.all([\n eventPromise,\n associationsPromise,\n sourcesPromise,\n sitesPromise,\n shapesPromise\n ])\n .then(response => {\n const result = {\n events: response[0],\n associations: response[1],\n sources: response[2],\n sites: response[3],\n shapes: response[4],\n notifications\n }\n if (Object.values(result).some(resp => resp.hasOwnProperty('error'))) {\n throw new Error('Some URLs returned negative. If you are in development, check the server is running')\n }\n dispatch(toggleFetchingDomain())\n dispatch(setInitialCategories(result.associations))\n return result\n })\n .catch(err => {\n dispatch(fetchError(err.message))\n dispatch(toggleFetchingDomain())\n // TODO: handle this appropriately in React hierarchy\n alert(err.message)\n })\n }\n}\n\nexport const FETCH_ERROR = 'FETCH_ERROR'\nexport function fetchError (message) {\n return {\n type: FETCH_ERROR,\n message\n }\n}\n\nexport const UPDATE_DOMAIN = 'UPDATE_DOMAIN'\nexport function updateDomain (payload) {\n return {\n type: UPDATE_DOMAIN,\n payload\n }\n}\n\nexport function fetchSource (source) {\n return dispatch => {\n if (!SOURCES_URL) {\n dispatch(fetchSourceError('No source extension specified.'))\n } else {\n dispatch(toggleFetchingSources())\n\n fetch(`${SOURCES_URL}`)\n .then(response => {\n if (!response.ok) {\n throw new Error('No sources are available at the URL specified in the config specified.')\n } else {\n return response.json()\n }\n })\n .catch(err => {\n dispatch(fetchSourceError(err.message))\n dispatch(toggleFetchingSources())\n })\n }\n }\n}\n\nexport const UPDATE_HIGHLIGHTED = 'UPDATE_HIGHLIGHTED'\nexport function updateHighlighted (highlighted) {\n return {\n type: UPDATE_HIGHLIGHTED,\n highlighted: highlighted\n }\n}\n\nexport const UPDATE_SELECTED = 'UPDATE_SELECTED'\nexport function updateSelected (selected) {\n return {\n type: UPDATE_SELECTED,\n selected: selected\n }\n}\n\nexport const UPDATE_DISTRICT = 'UPDATE_DISTRICT'\nexport function updateDistrict (district) {\n return {\n type: UPDATE_DISTRICT,\n district\n }\n}\n\nexport const CLEAR_FILTER = 'CLEAR_FILTER'\nexport function clearFilter (filter) {\n return {\n type: CLEAR_FILTER,\n filter\n }\n}\n\nexport const TOGGLE_ASSOCIATIONS = 'TOGGLE_ASSOCIATIONS'\nexport function toggleAssociations (association, value, shouldColor) {\n return {\n type: TOGGLE_ASSOCIATIONS,\n association,\n value,\n shouldColor\n }\n}\n\nexport const SET_LOADING = 'SET_LOADING'\nexport function setLoading () {\n return {\n type: SET_LOADING\n }\n}\n\nexport const SET_NOT_LOADING = 'SET_NOT_LOADING'\nexport function setNotLoading () {\n return {\n type: SET_NOT_LOADING\n }\n}\n\nexport const SET_INITIAL_CATEGORIES = 'SET_INITIAL_CATEGORIES'\nexport function setInitialCategories (values) {\n return {\n type: SET_INITIAL_CATEGORIES,\n values\n }\n}\n\nexport const UPDATE_TIMERANGE = 'UPDATE_TIMERANGE'\nexport function updateTimeRange (timerange) {\n return {\n type: UPDATE_TIMERANGE,\n timerange\n }\n}\n\nexport const UPDATE_DIMENSIONS = 'UPDATE_DIMENSIONS'\nexport function updateDimensions (dims) {\n return {\n type: UPDATE_DIMENSIONS,\n dims\n }\n}\n\nexport const UPDATE_NARRATIVE = 'UPDATE_NARRATIVE'\nexport function updateNarrative (narrative) {\n return {\n type: UPDATE_NARRATIVE,\n narrative\n }\n}\n\nexport const UPDATE_NARRATIVE_STEP_IDX = 'UPDATE_NARRATIVE_STEP_IDX'\nexport function updateNarrativeStepIdx (idx) {\n return {\n type: UPDATE_NARRATIVE_STEP_IDX,\n idx\n }\n}\n\nexport const UPDATE_SOURCE = 'UPDATE_SOURCE'\nexport function updateSource (source) {\n return {\n type: UPDATE_SOURCE,\n source\n }\n}\n\nexport const UPDATE_COLORING_SET = 'UPDATE_COLORING_SET'\nexport function updateColoringSet (coloringSet) {\n return {\n type: UPDATE_COLORING_SET,\n coloringSet\n }\n}\n\n// UI\n\nexport const TOGGLE_SITES = 'TOGGLE_SITES'\nexport function toggleSites () {\n return {\n type: TOGGLE_SITES\n }\n}\n\nexport const TOGGLE_FETCHING_DOMAIN = 'TOGGLE_FETCHING_DOMAIN'\nexport function toggleFetchingDomain () {\n return {\n type: TOGGLE_FETCHING_DOMAIN\n }\n}\n\nexport const TOGGLE_FETCHING_SOURCES = 'TOGGLE_FETCHING_SOURCES'\nexport function toggleFetchingSources () {\n return {\n type: TOGGLE_FETCHING_SOURCES\n }\n}\n\nexport const TOGGLE_LANGUAGE = 'TOGGLE_LANGUAGE'\nexport function toggleLanguage (language) {\n return {\n type: TOGGLE_LANGUAGE,\n language\n }\n}\n\nexport const CLOSE_TOOLBAR = 'CLOSE_TOOLBAR'\nexport function closeToolbar () {\n return {\n type: CLOSE_TOOLBAR\n }\n}\n\nexport const TOGGLE_INFOPOPUP = 'TOGGLE_INFOPOPUP'\nexport function toggleInfoPopup () {\n return {\n type: TOGGLE_INFOPOPUP\n }\n}\n\nexport const TOGGLE_INTROPOPUP = 'TOGGLE_INTROPOPUP'\nexport function toggleIntroPopup () {\n return {\n type: TOGGLE_INTROPOPUP\n }\n}\n\nexport const TOGGLE_NOTIFICATIONS = 'TOGGLE_NOTIFICATIONS'\nexport function toggleNotifications () {\n return {\n type: TOGGLE_NOTIFICATIONS\n }\n}\n\nexport const MARK_NOTIFICATIONS_READ = 'MARK_NOTIFICATIONS_READ'\nexport function markNotificationsRead () {\n return {\n type: MARK_NOTIFICATIONS_READ\n }\n}\n\nexport const TOGGLE_COVER = 'TOGGLE_COVER'\nexport function toggleCover () {\n return {\n type: TOGGLE_COVER\n }\n}\n\nexport const UPDATE_SEARCH_QUERY = 'UPDATE_SEARCH_QUERY'\nexport function updateSearchQuery (searchQuery) {\n return {\n type: UPDATE_SEARCH_QUERY,\n searchQuery\n }\n}\n\n// ERRORS\n\nexport const FETCH_SOURCE_ERROR = 'FETCH_SOURCE_ERROR'\nexport function fetchSourceError (msg) {\n return {\n type: FETCH_SOURCE_ERROR,\n msg\n }\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/presentational/Map/ColoredMarkers.jsx",[],"/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Controls.js",["338"],"import React from 'react'\n\nexport default ({ viewIdx, paths, onShiftHandler }) => {\n const backArrow = viewIdx !== 0 ? (\n onShiftHandler(-1)}\n >\n
\n arrow_left\n
\n
\n ) : null\n const forwardArrow = viewIdx < paths.length - 1 ? (\n onShiftHandler(1)}\n >\n
\n arrow_right\n
\n
\n ) : null\n\n if (paths.length > 1) {\n return (\n
\n {backArrow}\n {forwardArrow}\n
\n )\n }\n return (\n
\n )\n}\n","/Users/zac/Developer/Forensic Architecture/timemap/src/components/Overlay/Content.js",["339","340"],"import React from 'react'\nimport { Player } from 'video-react'\nimport Img from 'react-image'\nimport Md from './Md'\nimport Spinner from '../presentational/Spinner'\nimport NoSource from '../presentational/NoSource'\n\nexport default ({ media, viewIdx, translations, switchLanguage, langIdx }) => {\n const el = document.querySelector(`.source-media-gallery`)\n const shiftW = el ? el.getBoundingClientRect().width : 0\n\n function renderMedia (media) {\n let { path, type, poster } = media\n switch (type) {\n case 'Image':\n return (\n
\n
}\n unloader={}\n onClick={() => window.open(path, '_blank')}\n />\n
\n )\n case 'Video':\n return (\n
\n
\n {translations ? translations.map((trans, idx) => (\n langIdx !== idx + 1 ? (\n
switchLanguage(idx + 1)}>{trans.code}
\n ) : (\n
switchLanguage(0)}>EN
\n )\n )) : null}\n
\n \n
\n )\n case 'Text':\n return (\n
\n }\n unloader={() => this.renderError()}\n />\n
\n )\n case 'Document':\n return (\n