From 32f88b60ec473f1069eda45c85abbe8a1c0e5d0d Mon Sep 17 00:00:00 2001 From: John Date: Tue, 20 Feb 2024 17:40:38 +0000 Subject: [PATCH] #178 Config context, some cleanup. - Use config context object everywhere where applicable. - Add craco to allow use of @ alias to make deep imports much clearer --- craco.config.cjs | 13 +++++ jsconfig.json | 9 ++++ src/components/info/Disclaimer/Disclaimer.css | 0 src/components/info/Disclaimer/Disclaimer.js | 6 +-- .../info/NetworksMetadata/NetworksMetadata.js | 11 +++-- .../ObservationCounts/ObservationCounts.js | 15 +++--- .../info/StationData/StationData.js | 16 +++--- src/components/main/App/App.js | 23 +++++---- src/components/main/Body/Body.js | 49 +++++++------------ src/components/main/Header/Header.js | 5 +- src/components/maps/StationMap/StationMap.js | 9 ++-- .../maps/StationPopup/StationPopup.js | 18 +++---- .../preview/StationPreview/EndDateControl.js | 2 +- .../preview/StationPreview/GraphsBlock.js | 6 +-- .../preview/StationPreview/HeaderBlock.js | 4 +- .../preview/StationPreview/NavBlock.js | 4 +- .../preview/StationPreview/PreviewGraph.js | 9 ++-- .../preview/StationPreview/RangeBlock.js | 14 +++--- 18 files changed, 113 insertions(+), 100 deletions(-) create mode 100644 craco.config.cjs create mode 100644 jsconfig.json delete mode 100644 src/components/info/Disclaimer/Disclaimer.css diff --git a/craco.config.cjs b/craco.config.cjs new file mode 100644 index 00000000..5d983e49 --- /dev/null +++ b/craco.config.cjs @@ -0,0 +1,13 @@ +const path = require("path"); + +// use some aliases to help reduce the ../../../ in our imports and make it more +// obvious where stuff is coming from. Note that for intellisense to work these should +// be mirrored in jsconfig.json + +module.exports = { + webpack: { + alias: { + "@": path.resolve(__dirname, "src"), + }, + }, +}; diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 00000000..22eddce5 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "target": "es6", + "baseUrl": "src", + "paths": { + "@/*": ["./*"] + } + } +} diff --git a/src/components/info/Disclaimer/Disclaimer.css b/src/components/info/Disclaimer/Disclaimer.css deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/info/Disclaimer/Disclaimer.js b/src/components/info/Disclaimer/Disclaimer.js index 17ca4cc1..807e797c 100644 --- a/src/components/info/Disclaimer/Disclaimer.js +++ b/src/components/info/Disclaimer/Disclaimer.js @@ -1,11 +1,9 @@ import React, { useState } from "react"; import { Button, Modal } from "react-bootstrap"; -import "./Disclaimer.css"; -import { useStore } from "../../../state/state-store"; -import { useConfig } from "../../../state/query-hooks/use-config"; +import { useConfigContext } from "@/state/context-hooks/use-config-context"; function Disclaimer() { - const { data: config } = useConfig(); + const config = useConfigContext(); const [acknowledged, setAcknowledged] = useState(!config.disclaimer.enabled); const acknowledge = () => setAcknowledged(true); diff --git a/src/components/info/NetworksMetadata/NetworksMetadata.js b/src/components/info/NetworksMetadata/NetworksMetadata.js index 4838e2cb..1e22a962 100644 --- a/src/components/info/NetworksMetadata/NetworksMetadata.js +++ b/src/components/info/NetworksMetadata/NetworksMetadata.js @@ -11,16 +11,17 @@ import { useReactTable, flexRender, } from "@tanstack/react-table"; -import logger from "../../../logger"; -import "./NetworksMetadata.css"; -import { useConfig } from "../../../state/query-hooks/use-config"; -import { useNetworks } from "../../../state/query-hooks/use-networks"; +import logger from "@/logger"; +import { useNetworks } from "@/state/query-hooks/use-networks"; +import useConfigContext from "@/state/context-hooks/use-config-context"; import { NetworkSpot } from "./NetworkSpot"; +import "./NetworksMetadata.css"; + logger.configure({ active: true }); function NetworksMetadata() { - const { data: config } = useConfig(); + const config = useConfigContext(); const { data: networks, isLoading, isError } = useNetworks(); const [sorting, setSorting] = React.useState([]); diff --git a/src/components/info/ObservationCounts/ObservationCounts.js b/src/components/info/ObservationCounts/ObservationCounts.js index c45b73c7..2a88ec5d 100644 --- a/src/components/info/ObservationCounts/ObservationCounts.js +++ b/src/components/info/ObservationCounts/ObservationCounts.js @@ -1,13 +1,14 @@ import PropTypes from "prop-types"; -import React, { useEffect, useState, useMemo } from "react"; +import React, { useMemo } from "react"; import { Table } from "react-bootstrap"; import { reduce } from "lodash/fp"; -import InfoPopup from "../../util/InfoPopup"; -import logger from "../../../logger"; -import { getTimer } from "../../../utils/timing"; +import InfoPopup from "@/components/util/InfoPopup"; +import logger from "@/logger"; +import { getTimer } from "@/utils/timing"; +import { useObservationCounts } from "@/state/query-hooks/use-observation-counts"; +import useConfigContext from "@/state/context-hooks/use-config-context"; + import "./ObservationCounts.css"; -import { useConfig } from "../../../state/query-hooks/use-config"; -import { useObservationCounts } from "../../../state/query-hooks/use-observation-counts"; logger.configure({ active: true }); const timer = getTimer("Observation count timing"); @@ -31,7 +32,7 @@ function ObservationCounts({ clipToDate, stations, }) { - const { data: config } = useConfig(); + const config = useConfigContext(); const { data: countData, isLoading, diff --git a/src/components/info/StationData/StationData.js b/src/components/info/StationData/StationData.js index 2cfc04f1..79d2aa96 100644 --- a/src/components/info/StationData/StationData.js +++ b/src/components/info/StationData/StationData.js @@ -3,16 +3,14 @@ import React, { useState } from "react"; import { Button, ButtonToolbar, Col, Row } from "react-bootstrap"; import capitalize from "lodash/fp/capitalize"; import map from "lodash/fp/map"; -import FileFormatSelector from "../../selectors/FileFormatSelector"; -import ClipToDateControl from "../../controls/ClipToDateControl"; -import ObservationCounts from "../../info/ObservationCounts"; -import InfoPopup from "../../util/InfoPopup"; - -import logger from "../../../logger"; +import FileFormatSelector from "@/components/selectors/FileFormatSelector"; +import ClipToDateControl from "@/components/controls/ClipToDateControl"; +import ObservationCounts from "@/components/info/ObservationCounts"; +import InfoPopup from "@/components/util/InfoPopup"; +import logger from "@/logger"; +import useConfigContext from "@/state/context-hooks/use-config-context"; import "./StationData.css"; -import { useConfig } from "../../../state/query-hooks/use-config"; - logger.configure({ active: true }); function StationData({ @@ -22,7 +20,7 @@ function StationData({ dataDownloadFilename, rowClasses, }) { - const { data: config } = useConfig(); + const config = useConfigContext(); const [fileFormat, setFileFormat] = useState(); const [clipToDate, setClipToDate] = useState(false); const toggleClipToDate = () => setClipToDate(!clipToDate); diff --git a/src/components/main/App/App.js b/src/components/main/App/App.js index 9e4400d8..b32ecf4e 100644 --- a/src/components/main/App/App.js +++ b/src/components/main/App/App.js @@ -1,13 +1,16 @@ import React from "react"; import { Container } from "react-bootstrap"; -import Disclaimer from "../../info/Disclaimer"; -import Header from "../Header/Header"; +import Disclaimer from "@/components/info/Disclaimer"; +import Header from "@/components/main/Header"; import { Outlet } from "react-router-dom"; +import { useConfigDefaults } from "@/state/client-server-hooks/use-config-defaults"; import "./App.css"; -import { useConfigDefaults } from "../../../state/client-server-hooks/use-config-defaults"; + +import { ConfigContext } from "@/state/context-hooks/use-config-context"; + export const App = () => { - const { isLoading, isError } = useConfigDefaults(); + const { data: config, isLoading, isError } = useConfigDefaults(); if (isError) { return
An Error occoured while loading the app configuration.
; @@ -18,11 +21,13 @@ export const App = () => { } return ( - - -
- - + + + +
+ + + ); }; diff --git a/src/components/main/Body/Body.js b/src/components/main/Body/Body.js index 03d5d160..5601839d 100644 --- a/src/components/main/Body/Body.js +++ b/src/components/main/Body/Body.js @@ -2,33 +2,27 @@ import React, { useEffect, useMemo, useState } from "react"; import { Col, Row, Tab, Tabs } from "react-bootstrap"; import Select from "react-select"; -import logger from "../../../logger"; -import { - dataDownloadFilename, - dataDownloadUrl, -} from "../../../api/pdp-data-service"; -import { - stationAreaFilter, - stationFilter, -} from "../../../utils/station-filtering"; -import StationMap from "../../maps/StationMap"; -import StationMetadata from "../../info/StationMetadata"; -import StationData from "../../info/StationData"; -import NetworksMetadata from "../../info/NetworksMetadata"; -import SelectionCounts from "../../info/SelectionCounts"; -import SelectionCriteria from "../../info/SelectionCriteria"; -import UnselectedThings from "../../info/UnselectedThings"; -import AdjustableColumns from "../../util/AdjustableColumns"; +import logger from "@/logger"; +import { dataDownloadFilename, dataDownloadUrl } from "@/api/pdp-data-service"; +import { stationAreaFilter, stationFilter } from "@/utils/station-filtering"; +import StationMap from "@/components/maps/StationMap"; +import StationMetadata from "@/components/info/StationMetadata"; +import StationData from "@/components/info/StationData"; +import NetworksMetadata from "@/components/info/NetworksMetadata"; +import SelectionCounts from "@/components/info/SelectionCounts"; +import SelectionCriteria from "@/components/info/SelectionCriteria"; +import UnselectedThings from "@/components/info/UnselectedThings"; +import AdjustableColumns from "@/components/util/AdjustableColumns"; import StationFilters, { useStationFiltering, -} from "../../controls/StationFilters"; -import baseMaps from "../../maps/baseMaps"; -import { useStore } from "../../../state/state-store"; +} from "@/components/controls/StationFilters"; +import baseMaps from "@/components/maps/baseMaps"; +import { useStore } from "@/state/client/state-store"; import { useShallow } from "zustand/react/shallow"; -import { useConfig } from "../../../state/query-hooks/use-config"; -import { useStations } from "../../../state/query-hooks/use-stations"; -import { useVariables } from "../../../state/query-hooks/use-variables"; -import { useNetworks } from "../../../state/query-hooks/use-networks"; +import { useStations } from "@/state/query-hooks/use-stations"; +import { useVariables } from "@/state/query-hooks/use-variables"; +import { useNetworks } from "@/state/query-hooks/use-networks"; +import useConfigContext from "@/state/context-hooks/use-config-context"; import { NoRenderContent } from "./NoRenderContent"; import css from "../common.module.css"; @@ -36,7 +30,7 @@ import css from "../common.module.css"; logger.configure({ active: true }); function Body() { - const { data: config } = useConfig(); + const config = useConfigContext(); const { data: stations, isLoading: isStationsLoading, @@ -47,11 +41,6 @@ function Body() { isLoading: isVariablesLoading, isError: isVariablesError, } = useVariables(); - const { - data: networks, - isLoading: networksLoading, - isError: networksError, - } = useNetworks(); const actions = useStore( useShallow((state) => ({ diff --git a/src/components/main/Header/Header.js b/src/components/main/Header/Header.js index 23199461..d8a78b71 100644 --- a/src/components/main/Header/Header.js +++ b/src/components/main/Header/Header.js @@ -1,10 +1,11 @@ import React from "react"; import { Row, Col } from "react-bootstrap"; +import { useConfigContext } from "@/state/context-hooks/use-config-context"; + import "./Header.css"; -import { useConfig } from "../../../state/query-hooks/use-config"; function Header() { - const { data: config } = useConfig(); + const config = useConfigContext(); return ( diff --git a/src/components/maps/StationMap/StationMap.js b/src/components/maps/StationMap/StationMap.js index f2bf5178..7de2ce77 100644 --- a/src/components/maps/StationMap/StationMap.js +++ b/src/components/maps/StationMap/StationMap.js @@ -46,15 +46,14 @@ import MapInfoDisplay from "../MapInfoDisplay"; import { defaultMarkerOptions, ManyStationMarkers } from "../StationMarkers"; import { layersToGeoJSONMultipolygon } from "../../../utils/geoJSON-leaflet"; -import logger from "../../../logger"; +import logger from "@/logger"; import "./StationMap.css"; -import { getTimer } from "../../../utils/timing"; +import { getTimer } from "@/utils/timing"; import { MapSpinner } from "pcic-react-leaflet-components"; import { useImmer } from "use-immer"; -import { useStore } from "../../../state/state-store"; import { StationRefresh } from "../StationRefresh/StationRefresh"; -import { useConfig } from "../../../state/query-hooks/use-config"; +import useConfigContext from "@/state/context-hooks/use-config-context"; logger.configure({ active: true }); const smtimer = getTimer("StationMarker timing"); @@ -76,7 +75,7 @@ function StationMap({ // should be true if and only if slow updates to the map are pending // due to an external update. }) { - const { data: config } = useConfig(); + const config = useConfigContext(); const userShapeLayerRef = useRef(); const handleChangedGeometryLayers = () => { diff --git a/src/components/maps/StationPopup/StationPopup.js b/src/components/maps/StationPopup/StationPopup.js index 37902461..f5bb6429 100644 --- a/src/components/maps/StationPopup/StationPopup.js +++ b/src/components/maps/StationPopup/StationPopup.js @@ -8,11 +8,9 @@ import flow from "lodash/fp/flow"; import map from "lodash/fp/map"; import join from "lodash/fp/join"; import chroma from "chroma-js"; -import FrequencySelector from "../../selectors/FrequencySelector"; +import FrequencySelector from "@/components/selectors/FrequencySelector"; -import logger from "../../../logger"; - -import "./StationPopup.css"; +import logger from "@/logger"; import { stationNetwork, uniqStationFreqs, @@ -20,17 +18,19 @@ import { uniqStationNames, uniqStationObsPeriods, uniqStationVariableNames, -} from "../../../utils/station-info"; -import { useConfig } from "../../../state/query-hooks/use-config"; -import { useNetworks } from "../../../state/query-hooks/use-networks"; -import { useVariables } from "../../../state/query-hooks/use-variables"; +} from "@/utils/station-info"; +import { useNetworks } from "@/state/query-hooks/use-networks"; +import { useVariables } from "@/state/query-hooks/use-variables"; + +import "./StationPopup.css"; +import useConfigContext from "@/state/context-hooks/use-config-context"; logger.configure({ active: true }); const formatDate = (d) => (d ? d.toISOString().substr(0, 10) : "unknown"); function StationPopup({ station }) { - const { data: config } = useConfig(); + const config = useConfigContext(); const { data: networks } = useNetworks(); const { data: variables } = useVariables(); diff --git a/src/components/preview/StationPreview/EndDateControl.js b/src/components/preview/StationPreview/EndDateControl.js index 23af76c6..d7f584dd 100644 --- a/src/components/preview/StationPreview/EndDateControl.js +++ b/src/components/preview/StationPreview/EndDateControl.js @@ -1,6 +1,6 @@ import { useState } from "react"; import DatePicker from "react-datepicker"; -import { useStore } from "../../../state/state-store"; +import { useStore } from "@/state/client/state-store"; import css from "./EndDateControl.module.css"; export const EndDateControl = () => { diff --git a/src/components/preview/StationPreview/GraphsBlock.js b/src/components/preview/StationPreview/GraphsBlock.js index 849a3583..3767a620 100644 --- a/src/components/preview/StationPreview/GraphsBlock.js +++ b/src/components/preview/StationPreview/GraphsBlock.js @@ -2,9 +2,9 @@ import React from "react"; import { Card, Col, Row } from "react-bootstrap"; import map from "lodash/fp/map"; import PreviewGraph from "./PreviewGraph"; -import { useStore } from "../../../state/state-store"; -import { useStation } from "../../../state/query-hooks/use-station"; -import { useStationVariables } from "../../../state/query-hooks/use-station-variables"; +import { useStore } from "@/state/client/state-store"; +import { useStation } from "@/state/query-hooks/use-station"; +import { useStationVariables } from "@/state/query-hooks/use-station-variables"; const GraphsBlock = () => { const stationId = useStore((state) => state.stationId); diff --git a/src/components/preview/StationPreview/HeaderBlock.js b/src/components/preview/StationPreview/HeaderBlock.js index 81ccf706..111c2e9f 100644 --- a/src/components/preview/StationPreview/HeaderBlock.js +++ b/src/components/preview/StationPreview/HeaderBlock.js @@ -2,8 +2,8 @@ import React from "react"; import { Link } from "react-router-dom"; import map from "lodash/fp/map"; import { Accordion, Table, Row, Col, Spinner } from "react-bootstrap"; -import { useStation } from "../../../state/query-hooks/use-station"; -import { useStore } from "../../../state/state-store"; +import { useStation } from "@/state/query-hooks/use-station"; +import { useStore } from "@/state/client/state-store"; export const HeaderBlock = () => { const stationId = useStore((state) => state.stationId); diff --git a/src/components/preview/StationPreview/NavBlock.js b/src/components/preview/StationPreview/NavBlock.js index 9561284b..3121893c 100644 --- a/src/components/preview/StationPreview/NavBlock.js +++ b/src/components/preview/StationPreview/NavBlock.js @@ -13,8 +13,8 @@ import { LinkContainer } from "react-router-bootstrap"; import { useShallow } from "zustand/react/shallow"; import RangeBlock from "./RangeBlock"; import EndDateControl from "./EndDateControl"; -import { useStationVariables } from "../../../state/query-hooks/use-station-variables"; -import { useStore } from "../../../state/state-store"; +import { useStationVariables } from "@/state/query-hooks/use-station-variables"; +import { useStore } from "@/state/client/state-store"; const NavBlock = () => { const data = useStore( diff --git a/src/components/preview/StationPreview/PreviewGraph.js b/src/components/preview/StationPreview/PreviewGraph.js index a65bc98e..c02cba9f 100644 --- a/src/components/preview/StationPreview/PreviewGraph.js +++ b/src/components/preview/StationPreview/PreviewGraph.js @@ -2,15 +2,16 @@ import React from "react"; import { Spinner } from "react-bootstrap"; import map from "lodash/fp/map"; import { useShallow } from "zustand/react/shallow"; -import { useStore } from "../../../state/state-store"; -import { useStationVariableObservations } from "../../../state/query-hooks/use-station-variable-observations"; +import { useStore } from "@/state/client/state-store"; +import { useStationVariableObservations } from "@/state/query-hooks/use-station-variable-observations"; +import { useConfigContext } from "@/state/context-hooks/use-config-context"; // Importing a smaller version of plotly allows us to significantly reduce the // bundle size (approx 5MB to 1MB) over the full version of plotly. // https://github.com/plotly/react-plotly.js?tab=readme-ov-file#customizing-the-plotlyjs-bundle import Plotly from "plotly.js-basic-dist"; import createPlotlyComponent from "react-plotly.js/factory"; -import { useConfig } from "../../../state/query-hooks/use-config"; + const Plot = createPlotlyComponent(Plotly); const PreviewGraph = ({ variableId }) => { @@ -23,7 +24,7 @@ const PreviewGraph = ({ variableId }) => { showLegend: state.showLegend, })), ); - const { data: config } = useConfig(); + const config = useConfigContext(); const { data: previewObservations, isLoading, diff --git a/src/components/preview/StationPreview/RangeBlock.js b/src/components/preview/StationPreview/RangeBlock.js index 50598608..6404b841 100644 --- a/src/components/preview/StationPreview/RangeBlock.js +++ b/src/components/preview/StationPreview/RangeBlock.js @@ -1,21 +1,19 @@ -import React, { useState, useEffect } from "react"; -import DateRange from "../../daterange"; -import startOfMonth from "date-fns/startOfMonth"; -import endOfMonth from "date-fns/endOfMonth"; +import React from "react"; +import DateRange from "@/components/daterange"; import addDays from "date-fns/addDays"; import differenceInDays from "date-fns/differenceInDays"; import differenceInYears from "date-fns/differenceInYears"; import startOfDecade from "date-fns/startOfDecade"; import endOfDecade from "date-fns/endOfDecade"; -import { useStore } from "../../../state/state-store"; -import { useConfig } from "../../../state/query-hooks/use-config"; -import { useStationVariables } from "../../../state/query-hooks/use-station-variables"; +import { useStore } from "@/state/client/state-store"; +import { useStationVariables } from "@/state/query-hooks/use-station-variables"; +import useConfigContext from "@/state/context-hooks/use-config-context"; const millisecondsPerMonth = 2629746000; const millisedondsPerDay = 86400000; const RangeBlock = ({}) => { - const { data: config } = useConfig(); + const config = useConfigContext(); const storeData = useStore((state) => ({ stationId: state.stationId, minStartDate: state.minStartDate,