From b437b87fc9c4ed97aa094d551e69bde5caf19f20 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Mon, 20 Jun 2022 01:19:15 -0400
Subject: [PATCH 1/8] Expand Scan Areas List
- Normalize manual areas
- Add parents property support
- Fix instanceof error
---
server/src/routes/rootRouter.js | 13 +--
server/src/services/api/fetchJson.js | 5 +-
server/src/services/config.js | 50 +++++++++---
src/components/QueryData.jsx | 6 +-
src/components/layout/drawer/Areas.jsx | 102 ++++++++++++++++--------
src/components/layout/drawer/Drawer.jsx | 3 +-
6 files changed, 114 insertions(+), 65 deletions(-)
diff --git a/server/src/routes/rootRouter.js b/server/src/routes/rootRouter.js
index 4a198dec3..dd61cf1d3 100644
--- a/server/src/routes/rootRouter.js
+++ b/server/src/routes/rootRouter.js
@@ -1,6 +1,5 @@
/* eslint-disable no-console */
const express = require('express')
-const { default: center } = require('@turf/center')
const authRouter = require('./authRouter')
const clientRouter = require('./clientRouter')
@@ -46,7 +45,7 @@ rootRouter.post('/clientError', (req) => {
rootRouter.get('/area/:area/:zoom?', (req, res) => {
const { area, zoom } = req.params
try {
- const { scanAreas, manualAreas } = config
+ const { scanAreas } = config
const validScanAreas = scanAreas[req.headers.host]
? scanAreas[req.headers.host]
: scanAreas.main
@@ -55,13 +54,7 @@ rootRouter.get('/area/:area/:zoom?', (req, res) => {
(a) => a.properties.name.toLowerCase() === area.toLowerCase(),
)
if (foundArea) {
- const [lon, lat] = center(foundArea).geometry.coordinates
- return res.redirect(`/@/${lat}/${lon}/${zoom || 18}`)
- }
- if (manualAreas.length) {
- const { lat, lon } = manualAreas.find(
- (a) => a.name.toLowerCase() === area.toLowerCase(),
- )
+ const [lat, lon] = foundArea.properties.center
return res.redirect(`/@/${lat}/${lon}/${zoom || 18}`)
}
return res.redirect('/404')
@@ -166,7 +159,6 @@ rootRouter.get('/settings', async (req, res) => {
react: {},
leaflet: {},
},
- manualAreas: config.manualAreas || {},
icons: { ...config.icons, styles: Event.uicons },
scanner: {
scannerType: config.scanner.backendConfig.platform,
@@ -199,7 +191,6 @@ rootRouter.get('/settings', async (req, res) => {
// keys that are being sent to the frontend but are not options
const ignoreKeys = [
'map',
- 'manualAreas',
'limit',
'icons',
'scanner',
diff --git a/server/src/services/api/fetchJson.js b/server/src/services/api/fetchJson.js
index 1e9946967..230e275aa 100644
--- a/server/src/services/api/fetchJson.js
+++ b/server/src/services/api/fetchJson.js
@@ -1,6 +1,5 @@
/* eslint-disable no-console */
const fetch = require('node-fetch')
-const { AbortError } = require('node-fetch')
module.exports = async function fetchJson(
url,
@@ -21,9 +20,7 @@ module.exports = async function fetchJson(
}
return response.json()
} catch (e) {
- if (e instanceof AbortError) {
- console.log('Request to', url, 'timed out and was aborted')
- } else if (log) {
+ if (log) {
console.warn(e)
} else if (e instanceof Error) {
console.warn(e.message, '\n', e.code, `\nUnable to fetch ${url}`)
diff --git a/server/src/services/config.js b/server/src/services/config.js
index bd88fb8d3..f805ddfee 100644
--- a/server/src/services/config.js
+++ b/server/src/services/config.js
@@ -4,14 +4,15 @@
process.env.NODE_CONFIG_DIR = `${__dirname}/../configs`
const fs = require('fs')
-const path = require('path')
+const { resolve } = require('path')
const dotenv = require('dotenv')
+const { default: center } = require('@turf/center')
dotenv.config()
const config = require('config')
-if (!fs.existsSync(path.resolve(`${__dirname}/../configs/local.json`))) {
+if (!fs.existsSync(resolve(`${__dirname}/../configs/local.json`))) {
// add database env variables from .env or docker-compose
const {
SCANNER_DB_HOST,
@@ -82,7 +83,7 @@ if (!fs.existsSync(path.resolve(`${__dirname}/../configs/local.json`))) {
)
}
}
-if (fs.existsSync(path.resolve(`${__dirname}/../configs/config.json`))) {
+if (fs.existsSync(resolve(`${__dirname}/../configs/config.json`))) {
console.log(
'[CONFIG] Config v1 (config.json) found, it is fine to leave it but make sure you are using and updating local.json instead.',
)
@@ -166,14 +167,44 @@ config.authMethods = [
})
// Load each areas.json
-const loadScanPolygons = (fileName) =>
- fs.existsSync(path.resolve(`${__dirname}/../configs/${fileName}`))
- ? require(`../configs/${fileName}`)
+const loadScanPolygons = (fileName) => {
+ const geojson = fs.existsSync(resolve(`${__dirname}/../configs/${fileName}`))
+ ? JSON.parse(fs.readFileSync(resolve(__dirname, `../configs/${fileName}`)))
: { features: [] }
+ return {
+ ...geojson,
+ features: geojson.features.map((f) => ({
+ ...f,
+ properties: {
+ ...f.properties,
+ center: center(f).geometry.coordinates.reverse(),
+ },
+ })),
+ }
+}
// Check if an areas.json exists
config.scanAreas = {
- main: loadScanPolygons(config.map.geoJsonFileName),
+ main: config.manualAreas.length
+ ? {
+ type: 'FeatureCollection',
+ features: config.manualAreas
+ .filter((area) => ['lat', 'lon', 'name'].every((k) => k in area))
+ .map((area) => ({
+ type: 'Feature',
+ properties: {
+ name: area.name,
+ center: [area.lat, area.lon],
+ zoom: area.zoom,
+ parent: area.parent,
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [[[area.lon, area.lat]]],
+ },
+ })),
+ }
+ : loadScanPolygons(config.map.geoJsonFileName),
...Object.fromEntries(
config.multiDomains.map((d) => [
d.general?.geoJsonFileName ? d.domain : 'main',
@@ -210,9 +241,4 @@ if (
config.authentication.alwaysEnabledPerms = enabled
}
-// Map manual areas
-config.manualAreas = Object.fromEntries(
- config.manualAreas.map((area) => [area.name, area]),
-)
-
module.exports = config
diff --git a/src/components/QueryData.jsx b/src/components/QueryData.jsx
index bd01d5e50..6af23c606 100644
--- a/src/components/QueryData.jsx
+++ b/src/components/QueryData.jsx
@@ -132,8 +132,8 @@ export default function QueryData({
}
}
- const renderedData = data || previousData || {}
- return renderedData[category] ? (
+ const renderedData = data || previousData || { [category]: [] }
+ return (
<>
)}
>
- ) : null
+ )
}
diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx
index 1c0eee568..b10172647 100644
--- a/src/components/layout/drawer/Areas.jsx
+++ b/src/components/layout/drawer/Areas.jsx
@@ -1,18 +1,36 @@
import React from 'react'
import { useQuery } from '@apollo/client'
-import { Paper, MenuItem, MenuList, Typography } from '@material-ui/core'
-import center from '@turf/center'
+import { Grid, Paper, MenuItem, Typography } from '@material-ui/core'
import { useMap } from 'react-leaflet'
import Utility from '@services/Utility'
import Query from '@services/Query'
-export default function AreaDropDown({ scanAreasZoom, manualAreas }) {
- const { data } = useQuery(Query.scanAreas(), {
+export default function AreaDropDown({ scanAreasZoom }) {
+ const { data, loading, error } = useQuery(Query.scanAreas(), {
variables: { version: inject.VERSION },
})
const map = useMap()
+ if (loading || error) return null
+
+ const stuff = React.useMemo(() => {
+ const parents = {}
+ data.scanAreas[0].features.forEach((feature) => {
+ if (feature.properties.parent && !parents[feature.properties.parent]) {
+ parents[feature.properties.parent] = {
+ details: data.scanAreas[0].features.find(
+ (area) => area.properties.name === feature.properties.parent,
+ ),
+ children: data.scanAreas[0].features.filter(
+ (area) => area.properties.parent === feature.properties.parent,
+ ),
+ }
+ }
+ })
+ return parents
+ }, [])
+
return (
- {Object.keys(manualAreas).length ? (
-
- {Object.keys(manualAreas).map((area) => (
-
- ))}
-
- ) : (
-
- {data &&
- data.scanAreas[0].features.map((area) => (
- {
- const [lon, lat] = center(area).geometry.coordinates
- map.flyTo([lat, lon], scanAreasZoom)
- }}
- >
-
- {Utility.getProperName(area.properties.name)}
+
+
+ {Utility.getProperName(feat.properties.name)}
- ))}
-
- )}
+
+ ))}
+
+ ))}
)
}
diff --git a/src/components/layout/drawer/Drawer.jsx b/src/components/layout/drawer/Drawer.jsx
index da5ff7985..8ca6426bf 100644
--- a/src/components/layout/drawer/Drawer.jsx
+++ b/src/components/layout/drawer/Drawer.jsx
@@ -36,7 +36,6 @@ export default function Sidebar({
const ui = useStatic((state) => state.ui)
const staticUserSettings = useStatic((state) => state.userSettings)
const {
- manualAreas,
map: { title, scanAreasZoom, noScanAreaOverlay, enableQuestSetSelector },
} = useStatic((state) => state.config)
const available = useStatic((s) => s.available)
@@ -137,7 +136,7 @@ export default function Sidebar({
)}
{category === 'scanAreas' && (
-
+
)}
From 7424eb7e7f59287f6a44094a86a665743b6bb180 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Mon, 20 Jun 2022 01:27:43 -0400
Subject: [PATCH 2/8] Borders & Fix for areas.json
---
src/components/layout/drawer/Areas.jsx | 59 ++++++++++++++++----------
1 file changed, 36 insertions(+), 23 deletions(-)
diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx
index b10172647..94108f1ce 100644
--- a/src/components/layout/drawer/Areas.jsx
+++ b/src/components/layout/drawer/Areas.jsx
@@ -14,7 +14,7 @@ export default function AreaDropDown({ scanAreasZoom }) {
if (loading || error) return null
- const stuff = React.useMemo(() => {
+ const areas = React.useMemo(() => {
const parents = {}
data.scanAreas[0].features.forEach((feature) => {
if (feature.properties.parent && !parents[feature.properties.parent]) {
@@ -28,6 +28,9 @@ export default function AreaDropDown({ scanAreasZoom }) {
}
}
})
+ if (!Object.keys(parents).length) {
+ parents[''] = { children: data.scanAreas[0].features }
+ }
return parents
}, [])
@@ -41,44 +44,54 @@ export default function AreaDropDown({ scanAreasZoom }) {
backgroundColor: '#212121',
}}
>
- {Object.entries(stuff).map(([parent, { details, children }]) => (
+ {Object.entries(areas).map(([parent, { details, children }]) => (
- {
- map.flyTo(
- details.properties.center,
- details.properties.zoom || scanAreasZoom,
- )
- }
- : undefined
- }
- >
-
-
- {Utility.getProperName(parent)}
-
-
-
+ {Boolean(parent) && (
+ {
+ map.flyTo(
+ details.properties.center,
+ details.properties.zoom || scanAreasZoom,
+ )
+ }
+ : undefined
+ }
+ style={{ border: '1px solid grey' }}
+ >
+
+
+ {Utility.getProperName(parent)}
+
+
+
+ )}
{children.map((feat, i) => (
{
map.flyTo(
feat.properties.center,
feat.properties.zoom || scanAreasZoom,
)
}}
+ style={{ border: '1px solid grey' }}
>
Date: Mon, 20 Jun 2022 09:22:12 -0400
Subject: [PATCH 3/8] Update Examples
---
server/src/configs/areas.example.json | 3 ++-
server/src/configs/local.example.json | 14 +++++++++++++-
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/server/src/configs/areas.example.json b/server/src/configs/areas.example.json
index 7d8b916f9..ff2fa9e31 100644
--- a/server/src/configs/areas.example.json
+++ b/server/src/configs/areas.example.json
@@ -34,7 +34,8 @@
"stroke": "#352BFF",
"stroke-width": 2.0,
"fill": "#0651FF",
- "hidden": false
+ "hidden": false,
+ "parent": "USA"
}
}
]
diff --git a/server/src/configs/local.example.json b/server/src/configs/local.example.json
index f7cc0591f..05ba899d1 100644
--- a/server/src/configs/local.example.json
+++ b/server/src/configs/local.example.json
@@ -302,10 +302,22 @@
"lon": -74.0174788,
"zoom": 15
},
+ {
+ "name": "California",
+ "lat": 37.1931249,
+ "lon": -123.7961458
+ },
{
"name": "San Francisco",
"lat": 37.79539194255634,
- "lon": -122.39333173075096
+ "lon": -122.39333173075096,
+ "parent": "California"
+ },
+ {
+ "name": "Houston",
+ "lat": 33.6145517,
+ "lon": -108.6038347,
+ "parent": "Texas"
}
]
}
\ No newline at end of file
From 047ecf0aaf74f33ffb2760f3a0e52c21a1fa29e4 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Mon, 20 Jun 2022 15:43:27 -0400
Subject: [PATCH 4/8] Better fill/stroke support
- Respect geojson fill and stroke colors
- Consolidate some of the logic into initial config instead of in resolvers
- Change the spacing on WithSubItems for better locale support
---
server/src/graphql/resolvers.js | 7 ---
server/src/services/config.js | 45 ++++++++++---------
src/components/layout/drawer/Areas.jsx | 14 ++++--
src/components/layout/drawer/WithSubItems.jsx | 4 +-
src/components/tiles/ScanArea.jsx | 6 ++-
5 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/server/src/graphql/resolvers.js b/server/src/graphql/resolvers.js
index d6d90151f..0ad7f4371 100644
--- a/server/src/graphql/resolvers.js
+++ b/server/src/graphql/resolvers.js
@@ -188,13 +188,6 @@ module.exports = {
? config.scanAreas[req.headers.host]
: config.scanAreas.main
if (perms?.scanAreas && scanAreas.features.length) {
- try {
- scanAreas.features = scanAreas.features
- .filter((feature) => !feature.properties.hidden)
- .sort((a, b) => (a.properties.name > b.properties.name ? 1 : -1))
- } catch (e) {
- console.warn('[WARN] Failed to sort scan areas', e.message)
- }
return [scanAreas]
}
return [{ features: [] }]
diff --git a/server/src/services/config.js b/server/src/services/config.js
index f805ddfee..32106e96e 100644
--- a/server/src/services/config.js
+++ b/server/src/services/config.js
@@ -173,13 +173,16 @@ const loadScanPolygons = (fileName) => {
: { features: [] }
return {
...geojson,
- features: geojson.features.map((f) => ({
- ...f,
- properties: {
- ...f.properties,
- center: center(f).geometry.coordinates.reverse(),
- },
- })),
+ features: geojson.features
+ .filter((f) => !f.properties.hidden)
+ .map((f) => ({
+ ...f,
+ properties: {
+ ...f.properties,
+ center: center(f).geometry.coordinates.reverse(),
+ },
+ }))
+ .sort((a, b) => a.properties.name.localeCompare(b.properties.name)),
}
}
@@ -190,19 +193,21 @@ config.scanAreas = {
type: 'FeatureCollection',
features: config.manualAreas
.filter((area) => ['lat', 'lon', 'name'].every((k) => k in area))
- .map((area) => ({
- type: 'Feature',
- properties: {
- name: area.name,
- center: [area.lat, area.lon],
- zoom: area.zoom,
- parent: area.parent,
- },
- geometry: {
- type: 'Polygon',
- coordinates: [[[area.lon, area.lat]]],
- },
- })),
+ .map((area) => {
+ const { lat, lon, ...rest } = area
+ return {
+ type: 'Feature',
+ properties: {
+ center: [lat, lon],
+ ...rest,
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [[[lon, lat]]],
+ },
+ }
+ })
+ .sort((a, b) => a.properties.name.localeCompare(b.properties.name)),
}
: loadScanPolygons(config.map.geoJsonFileName),
...Object.fromEntries(
diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx
index 94108f1ce..1bd11acb7 100644
--- a/src/components/layout/drawer/Areas.jsx
+++ b/src/components/layout/drawer/Areas.jsx
@@ -15,7 +15,7 @@ export default function AreaDropDown({ scanAreasZoom }) {
if (loading || error) return null
const areas = React.useMemo(() => {
- const parents = {}
+ const parents = { '': { children: [] } }
data.scanAreas[0].features.forEach((feature) => {
if (feature.properties.parent && !parents[feature.properties.parent]) {
parents[feature.properties.parent] = {
@@ -26,6 +26,8 @@ export default function AreaDropDown({ scanAreasZoom }) {
(area) => area.properties.parent === feature.properties.parent,
),
}
+ } else {
+ parents[''].children.push(feature)
}
})
if (!Object.keys(parents).length) {
@@ -65,7 +67,10 @@ export default function AreaDropDown({ scanAreasZoom }) {
}
: undefined
}
- style={{ border: '1px solid grey' }}
+ style={{
+ border: `1px solid ${details.properties.color || 'grey'}`,
+ backgroundColor: details.properties.fillColor || 'none',
+ }}
>
-
+
{category === 'scanAreas'
? t('show_polygons')
: t(Utility.camelToSnake(subItem))}
-
+
{filterCategory}
{enableQuestSetSelector === true &&
diff --git a/src/components/tiles/ScanArea.jsx b/src/components/tiles/ScanArea.jsx
index 721974595..0186ad0dc 100644
--- a/src/components/tiles/ScanArea.jsx
+++ b/src/components/tiles/ScanArea.jsx
@@ -20,10 +20,12 @@ export default function ScanAreaTile({
const name = feature.properties.name.toLowerCase()
const popupContent = Utility.getProperName(name)
layer.setStyle({
- color: feature.properties.stroke || '#3388ff',
+ color:
+ feature.properties.color || feature.properties.stroke || '#3388ff',
weight: feature.properties['stroke-width'] || 3,
opacity: feature.properties['stroke-opacity'] || 1,
- fillColor: feature.properties.fill || '#3388ff',
+ fillColor:
+ feature.properties.fillColor || feature.properties.fill || '#3388ff',
fillOpacity:
selectedAreas &&
selectedAreas.includes(name) &&
From 6b6a9d1c88dd3e28ff95faa1d90ecc6be9d13e18 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Mon, 20 Jun 2022 16:13:19 -0400
Subject: [PATCH 5/8] Fallback catches
---
src/components/layout/drawer/Areas.jsx | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx
index 1bd11acb7..d02f95e02 100644
--- a/src/components/layout/drawer/Areas.jsx
+++ b/src/components/layout/drawer/Areas.jsx
@@ -60,16 +60,18 @@ export default function AreaDropDown({ scanAreasZoom }) {
onClick={
details
? () => {
- map.flyTo(
- details.properties.center,
- details.properties.zoom || scanAreasZoom,
- )
+ if (details?.properties) {
+ map.flyTo(
+ details.properties.center,
+ details.properties.zoom || scanAreasZoom,
+ )
+ }
}
: undefined
}
style={{
- border: `1px solid ${details.properties.color || 'grey'}`,
- backgroundColor: details.properties.fillColor || 'none',
+ border: `1px solid ${details?.properties?.color || 'grey'}`,
+ backgroundColor: details?.properties?.fillColor || 'none',
}}
>
From 304273578396e782f0fd181aa0c0ae8bcdca8b64 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Mon, 20 Jun 2022 16:34:13 -0400
Subject: [PATCH 6/8] Better odd count handling
---
src/components/layout/drawer/Areas.jsx | 27 ++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx
index d02f95e02..e3f2b12c6 100644
--- a/src/components/layout/drawer/Areas.jsx
+++ b/src/components/layout/drawer/Areas.jsx
@@ -33,6 +33,11 @@ export default function AreaDropDown({ scanAreasZoom }) {
if (!Object.keys(parents).length) {
parents[''] = { children: data.scanAreas[0].features }
}
+ Object.values(parents).forEach(({ children }) => {
+ if (children.length % 2 === 1) {
+ children.push({ type: 'Feature', properties: { name: '' } })
+ }
+ })
return parents
}, [])
@@ -40,7 +45,7 @@ export default function AreaDropDown({ scanAreasZoom }) {
-
+
{
- map.flyTo(
- feat.properties.center,
- feat.properties.zoom || scanAreasZoom,
- )
+ if (feat.properties?.center) {
+ map.flyTo(
+ feat.properties.center,
+ feat.properties.zoom || scanAreasZoom,
+ )
+ }
}}
style={{
border: `1px solid ${feat.properties.color || 'grey'}`,
backgroundColor: feat.properties.fillColor || 'none',
}}
>
-
+
- {Utility.getProperName(feat.properties.name)}
+ {feat.properties.name ? (
+ Utility.getProperName(feat.properties.name)
+ ) : (
+ <> >
+ )}
From f6e8c6a827e5d0553458be4a40fed56948727d43 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Mon, 20 Jun 2022 22:41:42 -0400
Subject: [PATCH 7/8] Move logic to the server
- Move parent finding logic to the server for simplicity
- Add a GQL endpoint and all other relevant code needed for that
- Add a configurable height value for the menu
---
.../configs/custom-environment-variables.json | 4 ++
server/src/configs/default.json | 1 +
server/src/graphql/mapTypes.js | 6 +++
server/src/graphql/resolvers.js | 13 ++++++
server/src/graphql/typeDefs.js | 1 +
server/src/services/config.js | 30 ++++++++++++++
src/components/layout/drawer/Areas.jsx | 41 ++++---------------
src/components/layout/drawer/Drawer.jsx | 13 +++++-
src/services/Query.js | 6 ++-
src/services/queries/scanAreas.js | 16 +++++++-
10 files changed, 92 insertions(+), 39 deletions(-)
diff --git a/server/src/configs/custom-environment-variables.json b/server/src/configs/custom-environment-variables.json
index 970c28d2c..9d440de4e 100644
--- a/server/src/configs/custom-environment-variables.json
+++ b/server/src/configs/custom-environment-variables.json
@@ -352,6 +352,10 @@
"__name": "MAP_MISC_NO_SCAN_AREA_OVERLAY",
"__format": "boolean"
},
+ "scanAreaMenuHeight": {
+ "__name": "MAP_MISC_SCAN_AREA_MENU_HEIGHT",
+ "__format": "number"
+ },
"permImageDir": "MAP_MISC_PERM_IMAGE_DIR",
"permArrayImages": {
"__name": "MAP_MISC_PERM_ARRAY_IMAGES",
diff --git a/server/src/configs/default.json b/server/src/configs/default.json
index 14b2e121a..1b052bf29 100644
--- a/server/src/configs/default.json
+++ b/server/src/configs/default.json
@@ -143,6 +143,7 @@
"enableUserProfile": true,
"enableQuestSetSelector": false,
"noScanAreaOverlay": false,
+ "scanAreaMenuHeight": 400,
"permImageDir": "images/perms",
"permArrayImages": false,
"clientTimeoutMinutes": 30,
diff --git a/server/src/graphql/mapTypes.js b/server/src/graphql/mapTypes.js
index 8e6762f48..89358869c 100644
--- a/server/src/graphql/mapTypes.js
+++ b/server/src/graphql/mapTypes.js
@@ -52,6 +52,12 @@ module.exports = gql`
features: [Feature]
}
+ type ScanAreasMenu {
+ name: String
+ details: Feature
+ children: [Feature]
+ }
+
type Search {
id: ID
name: String
diff --git a/server/src/graphql/resolvers.js b/server/src/graphql/resolvers.js
index 0ad7f4371..53a7d11be 100644
--- a/server/src/graphql/resolvers.js
+++ b/server/src/graphql/resolvers.js
@@ -192,6 +192,19 @@ module.exports = {
}
return [{ features: [] }]
},
+ scanAreasMenu: (_, args, { perms, version, req }) => {
+ if (args.version && args.version !== version)
+ throw new UserInputError('old_client')
+ if (!perms) throw new AuthenticationError('session_expired')
+
+ const scanAreas = config.scanAreasMenu[req.headers.host]
+ ? config.scanAreasMenu[req.headers.host]
+ : config.scanAreasMenu.main
+ if (perms?.scanAreas && scanAreas.length) {
+ return scanAreas
+ }
+ return []
+ },
search: async (_, args, { Event, perms, version, Db }) => {
if (args.version && args.version !== version)
throw new UserInputError('old_client')
diff --git a/server/src/graphql/typeDefs.js b/server/src/graphql/typeDefs.js
index 80ca90aa6..867e79487 100644
--- a/server/src/graphql/typeDefs.js
+++ b/server/src/graphql/typeDefs.js
@@ -77,6 +77,7 @@ module.exports = gql`
version: String
): [ScanCell]
scanAreas(version: String): [ScanArea]
+ scanAreasMenu(version: String): [ScanAreasMenu]
search(
search: String
category: String
diff --git a/server/src/services/config.js b/server/src/services/config.js
index 32106e96e..2a3974338 100644
--- a/server/src/services/config.js
+++ b/server/src/services/config.js
@@ -220,6 +220,36 @@ config.scanAreas = {
),
}
+config.scanAreasMenu = Object.fromEntries(
+ Object.entries(config.scanAreas).map(([domain, areas]) => {
+ const parents = { '': { children: [], name: '' } }
+ areas.features.forEach((feature) => {
+ if (feature.properties.parent) {
+ parents[feature.properties.parent] = {
+ name: feature.properties.parent,
+ details: areas.features.find(
+ (area) => area.properties.name === feature.properties.parent,
+ ),
+ children: [],
+ }
+ }
+ })
+ areas.features.forEach((feature) => {
+ if (feature.properties.parent) {
+ parents[feature.properties.parent].children.push(feature)
+ } else if (!parents[feature.properties.name]) {
+ parents[''].children.push(feature)
+ }
+ })
+ Object.values(parents).forEach(({ children }) => {
+ if (children.length % 2 === 1) {
+ children.push({ type: 'Feature', properties: { name: '' } })
+ }
+ })
+ return [domain, Object.values(parents)]
+ }),
+)
+
config.api.pvp.leagueObj = Object.fromEntries(
config.api.pvp.leagues.map((league) => [league.name, league.cp]),
)
diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx
index e3f2b12c6..512d0dbd9 100644
--- a/src/components/layout/drawer/Areas.jsx
+++ b/src/components/layout/drawer/Areas.jsx
@@ -6,59 +6,32 @@ import { useMap } from 'react-leaflet'
import Utility from '@services/Utility'
import Query from '@services/Query'
-export default function AreaDropDown({ scanAreasZoom }) {
- const { data, loading, error } = useQuery(Query.scanAreas(), {
+export default function AreaDropDown({ scanAreaMenuHeight, scanAreasZoom }) {
+ const { data, loading, error } = useQuery(Query.scanAreasMenu(), {
variables: { version: inject.VERSION },
})
const map = useMap()
if (loading || error) return null
- const areas = React.useMemo(() => {
- const parents = { '': { children: [] } }
- data.scanAreas[0].features.forEach((feature) => {
- if (feature.properties.parent && !parents[feature.properties.parent]) {
- parents[feature.properties.parent] = {
- details: data.scanAreas[0].features.find(
- (area) => area.properties.name === feature.properties.parent,
- ),
- children: data.scanAreas[0].features.filter(
- (area) => area.properties.parent === feature.properties.parent,
- ),
- }
- } else {
- parents[''].children.push(feature)
- }
- })
- if (!Object.keys(parents).length) {
- parents[''] = { children: data.scanAreas[0].features }
- }
- Object.values(parents).forEach(({ children }) => {
- if (children.length % 2 === 1) {
- children.push({ type: 'Feature', properties: { name: '' } })
- }
- })
- return parents
- }, [])
-
return (
- {Object.entries(areas).map(([parent, { details, children }]) => (
+ {data?.scanAreasMenu?.map(({ name, details, children }) => (
- {Boolean(parent) && (
+ {Boolean(name) && (
- {Utility.getProperName(parent)}
+ {Utility.getProperName(name)}
diff --git a/src/components/layout/drawer/Drawer.jsx b/src/components/layout/drawer/Drawer.jsx
index 8ca6426bf..d20a44639 100644
--- a/src/components/layout/drawer/Drawer.jsx
+++ b/src/components/layout/drawer/Drawer.jsx
@@ -36,7 +36,13 @@ export default function Sidebar({
const ui = useStatic((state) => state.ui)
const staticUserSettings = useStatic((state) => state.userSettings)
const {
- map: { title, scanAreasZoom, noScanAreaOverlay, enableQuestSetSelector },
+ map: {
+ title,
+ scanAreasZoom,
+ scanAreaMenuHeight,
+ noScanAreaOverlay,
+ enableQuestSetSelector,
+ },
} = useStatic((state) => state.config)
const available = useStatic((s) => s.available)
const { t } = useTranslation()
@@ -136,7 +142,10 @@ export default function Sidebar({
)}
{category === 'scanAreas' && (
-
+
)}
diff --git a/src/services/Query.js b/src/services/Query.js
index 57233a313..256301ac9 100644
--- a/src/services/Query.js
+++ b/src/services/Query.js
@@ -8,7 +8,7 @@ import getAllWeather from './queries/weather'
import getAllScanCells from './queries/scanCell'
import getAllSubmissionCells from './queries/submissionCells'
import { getOne, getAllNests } from './queries/nest'
-import getAllScanAreas from './queries/scanAreas'
+import { getAllScanAreas, getScanAreasMenu } from './queries/scanAreas'
import * as searchIndex from './queries/search'
import * as webhookIndex from './queries/webhook'
import scanner from './queries/scanner'
@@ -122,6 +122,10 @@ export default class Query {
return getAllScanAreas
}
+ static scanAreasMenu() {
+ return getScanAreasMenu
+ }
+
static search(category) {
switch (category) {
case 'raids':
diff --git a/src/services/queries/scanAreas.js b/src/services/queries/scanAreas.js
index 73092dc1a..ebc64d74c 100644
--- a/src/services/queries/scanAreas.js
+++ b/src/services/queries/scanAreas.js
@@ -1,6 +1,6 @@
import { gql } from '@apollo/client'
-const getAllScanAreas = gql`
+export const getAllScanAreas = gql`
query ScanAreas($version: String) {
scanAreas(version: $version) {
type
@@ -16,4 +16,16 @@ const getAllScanAreas = gql`
}
`
-export default getAllScanAreas
+export const getScanAreasMenu = gql`
+ query ScanAreasMenu($version: String) {
+ scanAreasMenu(version: $version) {
+ name
+ details {
+ properties
+ }
+ children {
+ properties
+ }
+ }
+ }
+`
From bd5297a586436b8018f7884aa625c119ca0e24c0 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Mon, 20 Jun 2022 22:46:47 -0400
Subject: [PATCH 8/8] Add color to the examples
---
server/src/configs/local.example.json | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/server/src/configs/local.example.json b/server/src/configs/local.example.json
index 05ba899d1..273bec007 100644
--- a/server/src/configs/local.example.json
+++ b/server/src/configs/local.example.json
@@ -300,12 +300,15 @@
"name": "New York",
"lat": 40.7481666,
"lon": -74.0174788,
- "zoom": 15
+ "zoom": 15,
+ "color": "blue"
},
{
"name": "California",
"lat": 37.1931249,
- "lon": -123.7961458
+ "lon": -123.7961458,
+ "color": "orange",
+ "fillColor": "purple"
},
{
"name": "San Francisco",