From 647c37cad32ad53008065b08b5e3ca1ad4ebdeac Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Sun, 26 Jun 2022 17:05:47 -0400
Subject: [PATCH 1/4] Lots of Refinments
- Add multiDomain and hidden support to manual areas
- Maintain hidden areas for areaRestriction purposes but still hide them from the map and sidebar menu
- Add a check in weather model to fix an edgecase
- *Allow* manualAreas and an areas.json to be used together
- Fix reset button
- Fix sidebar menu grid items when the name is too long, assuming it's a multi-word place
- Less hacky ScanArea tile stuff
---
server/src/configs/local.example.json | 6 +-
server/src/graphql/resolvers.js | 23 +++---
server/src/models/Weather.js | 13 ++--
server/src/services/config.js | 73 +++++++++++--------
server/src/services/functions/getAreaSql.js | 7 +-
src/components/layout/drawer/AreaTile.jsx | 79 ++++++++++++---------
src/components/layout/drawer/Areas.jsx | 10 +--
src/components/tiles/ScanArea.jsx | 5 +-
src/hooks/useStore.js | 4 +-
9 files changed, 123 insertions(+), 97 deletions(-)
diff --git a/server/src/configs/local.example.json b/server/src/configs/local.example.json
index 273bec007..7c73ab3e9 100644
--- a/server/src/configs/local.example.json
+++ b/server/src/configs/local.example.json
@@ -314,13 +314,15 @@
"name": "San Francisco",
"lat": 37.79539194255634,
"lon": -122.39333173075096,
- "parent": "California"
+ "parent": "California",
+ "hidden": false
},
{
"name": "Houston",
"lat": 33.6145517,
"lon": -108.6038347,
- "parent": "Texas"
+ "parent": "Texas",
+ "domain": "map_2.your_map.com"
}
]
}
\ No newline at end of file
diff --git a/server/src/graphql/resolvers.js b/server/src/graphql/resolvers.js
index 6e10fe204..d0be2763f 100644
--- a/server/src/graphql/resolvers.js
+++ b/server/src/graphql/resolvers.js
@@ -168,17 +168,18 @@ module.exports = {
if (clientV !== serverV) throw new UserInputError('old_client')
if (!perms) throw new AuthenticationError('session_expired')
- const scanAreas = config.scanAreas[req.headers.host]
- ? config.scanAreas[req.headers.host]
- : config.scanAreas.main
- if (perms?.scanAreas && scanAreas.features.length) {
+ if (perms?.scanAreas) {
+ const scanAreas = config.scanAreas[req.headers.host]
+ ? config.scanAreas[req.headers.host]
+ : config.scanAreas.main
return [
{
...scanAreas,
features: scanAreas.features.filter(
(feature) =>
- !perms.areaRestrictions.length ||
- perms.areaRestrictions.includes(feature.properties.name),
+ !feature.properties.hidden &&
+ (!perms.areaRestrictions.length ||
+ perms.areaRestrictions.includes(feature.properties.name)),
),
},
]
@@ -189,10 +190,11 @@ module.exports = {
if (clientV !== serverV) 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) {
+ if (perms?.scanAreas) {
+ const scanAreas = config.scanAreasMenu[req.headers.host]
+ ? config.scanAreasMenu[req.headers.host]
+ : config.scanAreasMenu.main
+
if (perms.areaRestrictions.length) {
const filtered = scanAreas
.map((parent) => ({
@@ -203,6 +205,7 @@ module.exports = {
}))
.filter((parent) => parent.children.length)
+ // Adds new blanks to account for area restrictions trimming some
filtered.forEach(({ children }) => {
if (children.length % 2 === 1) {
children.push({
diff --git a/server/src/models/Weather.js b/server/src/models/Weather.js
index fb7f53217..344b2faad 100644
--- a/server/src/models/Weather.js
+++ b/server/src/models/Weather.js
@@ -52,15 +52,16 @@ module.exports = class Weather extends Model {
!merged.length ||
merged.some(
(area) =>
- pointInPolygon(
+ config.scanAreasObj[area] &&
+ (pointInPolygon(
point(config.scanAreasObj[area].geometry.coordinates[0][0]),
geojson,
) ||
- pointInPolygon(
- point([cell.longitude, cell.latitude]),
- config.scanAreasObj[area],
- ) ||
- booleanOverlap(geojson, config.scanAreasObj[area]),
+ pointInPolygon(
+ point([cell.longitude, cell.latitude]),
+ config.scanAreasObj[area],
+ ) ||
+ booleanOverlap(geojson, config.scanAreasObj[area])),
)
return (
hasOverlap && {
diff --git a/server/src/services/config.js b/server/src/services/config.js
index 6e898d2e4..4de2fbb65 100644
--- a/server/src/services/config.js
+++ b/server/src/services/config.js
@@ -166,51 +166,52 @@ config.authMethods = [
}
})
+const manualGeojson = {
+ type: 'FeatureCollection',
+ features: config.manualAreas
+ .filter((area) => ['lat', 'lon', 'name'].every((k) => k in area && !area.hidden))
+ .map((area) => {
+ const { lat, lon, ...rest } = area
+ return {
+ type: 'Feature',
+ properties: {
+ center: [lat, lon],
+ manual: true,
+ ...rest,
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [[[lon, lat]]],
+ },
+ }
+ }),
+}
+
// Load each areas.json
-const loadScanPolygons = (fileName) => {
+const loadScanPolygons = (fileName, domain) => {
const geojson = fs.existsSync(resolve(`${__dirname}/../configs/${fileName}`))
? JSON.parse(fs.readFileSync(resolve(__dirname, `../configs/${fileName}`)))
: { features: [] }
return {
...geojson,
- features: geojson.features
- .filter((f) => !f.properties.hidden)
- .map((f) => ({
+ features: [
+ ...manualGeojson.features.filter(
+ (f) => !f.properties.domain || f.properties.domain === domain,
+ ),
+ ...geojson.features.map((f) => ({
...f,
properties: {
...f.properties,
center: center(f).geometry.coordinates.reverse(),
},
- }))
- .sort((a, b) => a.properties.name.localeCompare(b.properties.name)),
+ })),
+ ].sort((a, b) => a.properties.name.localeCompare(b.properties.name)),
}
}
// Check if an areas.json exists
config.scanAreas = {
- main: config.manualAreas.length
- ? {
- type: 'FeatureCollection',
- features: config.manualAreas
- .filter((area) => ['lat', 'lon', 'name'].every((k) => k in area))
- .map((area) => {
- const { lat, lon, ...rest } = area
- return {
- type: 'Feature',
- properties: {
- center: [lat, lon],
- manual: true,
- ...rest,
- },
- geometry: {
- type: 'Polygon',
- coordinates: [[[lon, lat]]],
- },
- }
- })
- .sort((a, b) => a.properties.name.localeCompare(b.properties.name)),
- }
- : loadScanPolygons(config.map.geoJsonFileName),
+ main: loadScanPolygons(config.map.geoJsonFileName),
...Object.fromEntries(
config.multiDomains.map((d) => [
d.general?.geoJsonFileName ? d.domain : 'main',
@@ -224,7 +225,13 @@ config.scanAreas = {
config.scanAreasMenu = Object.fromEntries(
Object.entries(config.scanAreas).map(([domain, areas]) => {
const parents = { '': { children: [], name: '' } }
- areas.features.forEach((feature) => {
+
+ const noHidden = {
+ ...areas,
+ features: areas.features.filter((f) => !f.properties.hidden),
+ }
+ // Finds unique parents and determines if the parents have their own properties
+ noHidden.features.forEach((feature) => {
if (feature.properties.parent) {
parents[feature.properties.parent] = {
name: feature.properties.parent,
@@ -235,13 +242,17 @@ config.scanAreasMenu = Object.fromEntries(
}
}
})
- areas.features.forEach((feature) => {
+
+ // Finds the children of each parent
+ noHidden.features.forEach((feature) => {
if (feature.properties.parent) {
parents[feature.properties.parent].children.push(feature)
} else if (!parents[feature.properties.name]) {
parents[''].children.push(feature)
}
})
+
+ // Create blanks for better formatting when there's an odd number of children
Object.values(parents).forEach(({ children }) => {
if (children.length % 2 === 1) {
children.push({
diff --git a/server/src/services/functions/getAreaSql.js b/server/src/services/functions/getAreaSql.js
index df85675ba..8871a76db 100644
--- a/server/src/services/functions/getAreaSql.js
+++ b/server/src/services/functions/getAreaSql.js
@@ -1,4 +1,3 @@
-const config = require('../config')
const areas = require('../areas')
module.exports = function getAreaRestrictionSql(
@@ -8,11 +7,7 @@ module.exports = function getAreaRestrictionSql(
isMad,
category,
) {
- if (
- !areaRestrictions?.length &&
- (!onlyAreas?.length || config.manualAreas.length)
- )
- return true
+ if (!areaRestrictions?.length && !onlyAreas?.length) return true
const cleanUserAreas = onlyAreas.filter((area) => areas.names.includes(area))
const consolidatedAreas = areaRestrictions.length
diff --git a/src/components/layout/drawer/AreaTile.jsx b/src/components/layout/drawer/AreaTile.jsx
index ad8178ab2..168154b66 100644
--- a/src/components/layout/drawer/AreaTile.jsx
+++ b/src/components/layout/drawer/AreaTile.jsx
@@ -21,13 +21,16 @@ export default function AreaTile({
const hasAll =
childAreas &&
- childAreas.every((c) => scanAreas.filter.areas.includes(c.properties.name))
+ childAreas.every(
+ (c) =>
+ c.properties.manual ||
+ scanAreas.filter.areas.includes(c.properties.name),
+ )
const hasSome =
childAreas &&
childAreas.some((c) => scanAreas.filter.areas.includes(c.properties.name))
- const hasManual = childAreas
- ? childAreas.some((c) => c.properties.manual)
- : feature.properties.manual
+ const hasManual =
+ feature?.properties?.manual || childAreas.every((c) => c.properties.manual)
return (
diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx
index d9003acdf..f1607570c 100644
--- a/src/components/layout/drawer/Areas.jsx
+++ b/src/components/layout/drawer/Areas.jsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, { useMemo } from 'react'
import { useQuery } from '@apollo/client'
import { Grid, Button, Paper } from '@material-ui/core'
import { useTranslation } from 'react-i18next'
@@ -12,10 +12,12 @@ export default function AreaDropDown({ scanAreaMenuHeight, scanAreasZoom }) {
const { t } = useTranslation()
const setAreas = useStore((s) => s.setAreas)
- const allAreas = React.useMemo(() => {
+ const allAreas = useMemo(() => {
if (data?.scanAreasMenu) {
return data.scanAreasMenu.flatMap((parent) =>
- parent.children.map((child) => child.properties.name),
+ parent.children
+ .filter((child) => !child.properties.manual)
+ .map((child) => child.properties.name),
)
}
return []
@@ -52,7 +54,7 @@ export default function AreaDropDown({ scanAreaMenuHeight, scanAreasZoom }) {
{name && (
diff --git a/src/components/tiles/ScanArea.jsx b/src/components/tiles/ScanArea.jsx
index 6629a4305..05386c8dc 100644
--- a/src/components/tiles/ScanArea.jsx
+++ b/src/components/tiles/ScanArea.jsx
@@ -13,6 +13,9 @@ export function ScanAreaTile({
userSettings,
}) {
const setAreas = useStore((s) => s.setAreas)
+ const names = item.features
+ .filter((f) => !f.properties.manual)
+ .map((f) => f.properties.name)
const handleClick = (name) => {
if (selectedAreas.includes(name)) {
@@ -53,7 +56,7 @@ export function ScanAreaTile({
if (webhookMode) {
layer.on('click', () => handleClick(name.toLowerCase()))
} else if (!feature.properties.manual) {
- layer.on('click', () => setAreas(name))
+ layer.on('click', () => setAreas(name, names))
}
}
}
diff --git a/src/hooks/useStore.js b/src/hooks/useStore.js
index b6da1c7e1..7e214920a 100644
--- a/src/hooks/useStore.js
+++ b/src/hooks/useStore.js
@@ -31,8 +31,8 @@ export const useStore = create(
...filters.scanAreas,
filter: {
...filters.scanAreas.filter,
- areas: [...existing].filter(
- (area) => !validAreas.length || validAreas.includes(area),
+ areas: [...existing].filter((area) =>
+ validAreas.includes(area),
),
},
},
From 88229c630291a26d148c06067fb67cbf9603cd24 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Sun, 26 Jun 2022 17:30:38 -0400
Subject: [PATCH 2/4] linting
---
server/src/services/config.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/server/src/services/config.js b/server/src/services/config.js
index 4de2fbb65..077f51351 100644
--- a/server/src/services/config.js
+++ b/server/src/services/config.js
@@ -169,7 +169,9 @@ config.authMethods = [
const manualGeojson = {
type: 'FeatureCollection',
features: config.manualAreas
- .filter((area) => ['lat', 'lon', 'name'].every((k) => k in area && !area.hidden))
+ .filter((area) =>
+ ['lat', 'lon', 'name'].every((k) => k in area && !area.hidden),
+ )
.map((area) => {
const { lat, lon, ...rest } = area
return {
From 40d3dd6ad4ac2ba6768400846d4bd6ffaed19599 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Sun, 26 Jun 2022 17:35:27 -0400
Subject: [PATCH 3/4] Update areas.js
---
server/src/services/areas.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/src/services/areas.js b/server/src/services/areas.js
index 525280a6c..b9d28da56 100644
--- a/server/src/services/areas.js
+++ b/server/src/services/areas.js
@@ -6,7 +6,7 @@ const loadAreas = () => {
const normalized = { type: 'FeatureCollection', features: [] }
Object.values(config.scanAreas).forEach((area) => {
if (area?.features.length) {
- normalized.features.push(...area.features)
+ normalized.features.push(...area.features.filter((f) => !f.manual))
}
})
return normalized
From 6a0b9711afd9c16d9866ec19ad050cb1661daec6 Mon Sep 17 00:00:00 2001
From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>
Date: Sun, 26 Jun 2022 17:36:59 -0400
Subject: [PATCH 4/4] Update default.json
---
server/src/configs/default.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/src/configs/default.json b/server/src/configs/default.json
index 236ed63e4..718171d47 100644
--- a/server/src/configs/default.json
+++ b/server/src/configs/default.json
@@ -94,7 +94,7 @@
"minZoom": 10,
"maxZoom": 18,
"interactionRangeZoom": 15,
- "scanAreasZoom": 12,
+ "scanAreasZoom": 15,
"scanCellsZoom": 13,
"submissionZoom": 15,
"activeWeatherZoom": 13,