Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/components/device/new/location-info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
GeolocateControl,
type MapRef,
type MarkerDragEvent,
} from 'react-map-gl'
} from 'react-map-gl/mapbox'
import { Input } from '@/components/ui/input'
import { Label } from '~/components/ui/label'
import 'mapbox-gl/dist/mapbox-gl.css'
Expand Down
5 changes: 2 additions & 3 deletions app/components/header/download.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type BBox } from 'geojson'
import { Download as DownloadIcon } from 'lucide-react'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useMap } from 'react-map-gl'
import { useMap } from 'react-map-gl/mapbox'
import { Form, useNavigation, useActionData } from 'react-router'
import { Button } from '../ui/button'
import { Checkbox } from '../ui/checkbox'
Expand Down Expand Up @@ -160,8 +160,7 @@ export default function Download(props: any) {
}

// Filter devices inside the current bounds
const bounds =
(mapRef?.getMap().getBounds().toArray().flat() as BBox) ?? undefined
const bounds = mapRef?.getMap().getBounds()?.toArray().flat() as BBox | undefined
const devicesInBounds =
bounds && bounds.length === 4
? devices.filter((device: any) => {
Expand Down
2 changes: 1 addition & 1 deletion app/components/header/nav-bar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AnimatePresence, motion } from 'framer-motion'
import { SearchIcon, XIcon } from 'lucide-react'
import { useState, useEffect, useRef, createContext } from 'react'
import { useTranslation } from 'react-i18next'
import { useMap } from 'react-map-gl'
import { useMap } from 'react-map-gl/mapbox'
import NavbarHandler from './nav-bar-handler'
import FilterVisualization from '~/components/map/filter-visualization'
import { type Device } from '~/schema'
Expand Down
2 changes: 1 addition & 1 deletion app/components/map/geocoder-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
Marker,
type MarkerProps,
type ControlPosition,
} from 'react-map-gl'
} from 'react-map-gl/mapbox'

type GeocoderControlProps = Omit<
GeocoderOptions,
Expand Down
2 changes: 1 addition & 1 deletion app/components/map/layers/cluster/box-marker.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AnimatePresence, motion } from 'framer-motion'
import { Box, Rocket } from 'lucide-react'
import { useState } from 'react'
import { type MarkerProps, Marker, useMap } from 'react-map-gl'
import { type MarkerProps, Marker, useMap } from 'react-map-gl/mapbox'
import { useMatches, useNavigate, useSearchParams } from 'react-router'
import { useGlobalCompareMode } from '~/components/device-detail/useGlobalCompareMode'
import { validLngLat } from '~/lib/location'
Expand Down
9 changes: 5 additions & 4 deletions app/components/map/layers/cluster/cluster-layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from 'geojson'
import debounce from 'lodash.debounce'
import { useMemo, useCallback, useState, useEffect } from 'react'
import { Marker, useMap } from 'react-map-gl'
import { Marker, useMap } from 'react-map-gl/mapbox'
import { type PointFeature } from 'supercluster'
import useSupercluster from 'use-supercluster'
import BoxMarker from './box-marker'
Expand Down Expand Up @@ -48,8 +48,8 @@ export default function ClusterLayer({
const { osem: mapRef } = useMap()

// the viewport bounds and zoom level
const [bounds, setBounds] = useState(
mapRef?.getMap().getBounds().toArray().flat() as BBox,
const [bounds, setBounds] = useState<BBox>(
(mapRef?.getMap().getBounds()?.toArray().flat() as BBox) ?? [0, 0, 0, 0]
)
const [zoom, setZoom] = useState(mapRef?.getZoom() || 0)

Expand All @@ -69,7 +69,8 @@ export default function ClusterLayer({
// debounce the change handler to prevent too many updates
const debouncedChangeHandler = debounce(() => {
if (!mapRef) return
setBounds(mapRef.getMap().getBounds().toArray().flat() as BBox)
const newBounds = mapRef.getMap().getBounds()?.toArray().flat() as BBox | undefined
if (newBounds) setBounds(newBounds)
setZoom(mapRef.getZoom())
}, DEBOUNCE_VALUE)

Expand Down
2 changes: 1 addition & 1 deletion app/components/map/layers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type LayerProps } from 'react-map-gl'
import { type LayerProps } from 'react-map-gl/mapbox'

// colors to use for the categories
const colors = ['#4EAF47', '#666', '#666', '#666']
Expand Down
12 changes: 6 additions & 6 deletions app/components/map/layers/mobile/mobile-box-layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import {
point,
} from '@turf/helpers'
import { type MultiLineString, type Point } from 'geojson'
import mapboxgl from 'mapbox-gl'
import mapboxgl, { type CircleLayerSpecification, type LineLayerSpecification } from 'mapbox-gl'
import { createContext, useContext, useEffect, useRef, useState } from 'react'
import { Layer, Source, useMap } from 'react-map-gl'
import { Layer, Source, useMap } from 'react-map-gl/mapbox'
import { HIGH_COLOR, LOW_COLOR, createPalette } from './color-palette'
import { type Sensor } from '~/schema'

Expand All @@ -31,11 +31,11 @@ export default function MobileBoxLayer({
}: {
sensor: Sensor
minColor?:
| mapboxgl.CirclePaint['circle-color']
| mapboxgl.LinePaint['line-color']
| NonNullable<CircleLayerSpecification['paint']>['circle-color']
| NonNullable<LineLayerSpecification['paint']>['line-color']
maxColor?:
| mapboxgl.CirclePaint['circle-color']
| mapboxgl.LinePaint['line-color']
| NonNullable<CircleLayerSpecification['paint']>['circle-color']
| NonNullable<LineLayerSpecification['paint']>['line-color']
}) {
const [sourceData, setSourceData] = useState<GeoJSON.FeatureCollection>()
const { hoveredPoint, setHoveredPoint } = useContext(HoveredPointContext)
Expand Down
2 changes: 1 addition & 1 deletion app/components/map/layers/mobile/mobile-overview-layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { format } from 'date-fns'
import { type FeatureCollection, type Point } from 'geojson'
import { CalendarClock } from 'lucide-react'
import { useState, useEffect, useMemo, useCallback } from 'react'
import { Source, Layer, useMap, Popup } from 'react-map-gl'
import { Source, Layer, useMap, Popup } from 'react-map-gl/mapbox'
import MapLegend from './mobile-overview-legend'
import {
type LocationPoint,
Expand Down
10 changes: 5 additions & 5 deletions app/components/map/map.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
type LayerSpecification,
type Map as MapboxMap,
type AnyLayer,
type MapboxEvent,
type MapEvent,
} from 'mapbox-gl'
import { forwardRef, useEffect, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
Expand All @@ -10,7 +10,7 @@ import {
type MapRef,
NavigationControl,
Map as ReactMap,
} from 'react-map-gl'
} from 'react-map-gl/mapbox'

const Map = forwardRef<MapRef, MapProps>(
({ children, mapStyle, ...props }, ref) => {
Expand All @@ -26,7 +26,7 @@ const Map = forwardRef<MapRef, MapProps>(

const mapboxLocale = locale.split('-')[0]

style.layers.forEach((layer: AnyLayer) => {
style.layers.forEach((layer: LayerSpecification) => {
if (!('layout' in layer) || !layer.layout) return

const layout = layer.layout as Record<string, unknown>
Expand Down Expand Up @@ -59,7 +59,7 @@ const Map = forwardRef<MapRef, MapProps>(
)

const handleMapLoad = useCallback(
(event: MapboxEvent<undefined>) => {
(event: {target: MapboxMap}) => {
updateMapLanguage(event.target as MapboxMap, i18n.language)
},
[updateMapLanguage, i18n.language],
Expand Down
2 changes: 1 addition & 1 deletion app/components/search/search-list.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Cpu, Globe, MapPin } from 'lucide-react'
import { useState, useEffect, useCallback, useContext } from 'react'
import { useMap } from 'react-map-gl'
import { useMap } from 'react-map-gl/mapbox'
import { useMatches, useNavigate, useSearchParams } from 'react-router'
import { useGlobalCompareMode } from '../device-detail/useGlobalCompareMode'
import { NavbarContext } from '../header/nav-bar'
Expand Down
26 changes: 6 additions & 20 deletions app/env.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
declare module 'react-router' {
// Your AppLoadContext used in v2
interface AppLoadContext {
cspNonce: any
serverBuild: any
}

// TODO: remove this once we've migrated to `Route.LoaderArgs` instead for our loaders
interface LoaderFunctionArgs {
context: AppLoadContext
unstable_pattern?: string | undefined
}

// TODO: remove this once we've migrated to `Route.ActionArgs` instead for our actions
interface ActionFunctionArgs {
context: AppLoadContext
unstable_pattern?: string | undefined
}
}

/**
* Module file to declare module augmentations for
* all environments of the app, e.g. react-router
*
* declare module 'react-router' {}
**/
export {} // necessary for TS to treat this as a module
2 changes: 1 addition & 1 deletion app/lib/search-map-helper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type LngLatBounds, type LngLatLike, type MapRef } from 'react-map-gl'
import { type LngLatBounds, type LngLatLike, type MapRef } from 'react-map-gl/mapbox'

/**
* The function that is called when the user clicks on a location without bbox property in the search results. It flies the map to the location and closes the search results.
Expand Down
5 changes: 3 additions & 2 deletions app/routes/account.confirm-email.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { redirect, type LoaderFunctionArgs } from 'react-router'
import { redirect } from 'react-router'
import { type Route } from './+types/account.confirm-email'
import { confirmEmail } from '~/lib/user-service.server'
import { getUserSession, authSessionStorage } from '~/utils/session.server'

export async function loader({ request }: LoaderFunctionArgs) {
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url)
const token = url.searchParams.get('token')

Expand Down
7 changes: 3 additions & 4 deletions app/routes/account.password-reset.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import {
type ActionFunctionArgs,
type LoaderFunctionArgs,
type MetaFunction,
Form,
Link,
Expand All @@ -14,6 +12,7 @@ import {
useSearchParams,
} from 'react-router'

import { type Route } from './+types/account.password-reset'
import Spinner from '~/components/spinner'
import { Button } from '~/components/ui/button'
import {
Expand Down Expand Up @@ -44,7 +43,7 @@ type ActionData = {
}
}

export async function loader({ request }: LoaderFunctionArgs) {
export async function loader({ request }: Route.LoaderArgs) {
const userId = await getUserId(request)
if (userId) return redirect('/explore')

Expand All @@ -54,7 +53,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
return data<LoaderData>({ token: token?.trim() || null })
}

export async function action({ request }: ActionFunctionArgs) {
export async function action({ request }: Route.ActionArgs) {
const formData = await request.formData()
const token = formData.get('token')?.toString().trim() ?? ''
const newPassword = formData.get('newPassword')?.toString() ?? ''
Expand Down
3 changes: 1 addition & 2 deletions app/routes/admin.devices.$deviceId.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useCallback, useMemo, useState } from 'react'
import { type MarkerDragEvent } from 'react-map-gl'
import { useMemo, useState } from 'react'
import { Form, Link, redirect, useActionData } from 'react-router'
import invariant from 'tiny-invariant'
import { type Route } from './+types/admin.devices.$deviceId'
Expand Down
4 changes: 2 additions & 2 deletions app/routes/api.boxes.$deviceId.$sensorId.measurements.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type ActionFunctionArgs } from 'react-router'
import z from 'zod'
import { type Route } from './+types/api.boxes.$deviceId.$sensorId.measurements'
import { getUserFromJwt } from '~/lib/jwt'
import { getUserDevices } from '~/models/device.server'
import {
Expand All @@ -9,7 +9,7 @@ import {
} from '~/models/measurement.server'
import { StandardResponse } from '~/utils/response-utils'

export async function action({ request, params }: ActionFunctionArgs) {
export async function action({ request, params }: Route.ActionArgs) {
try {
const { deviceId, sensorId } = params
if (!deviceId || !sensorId)
Expand Down
12 changes: 7 additions & 5 deletions app/routes/api.boxes.$deviceId.$sensorId.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { type ActionFunction, type ActionFunctionArgs } from 'react-router'
import { type Route } from './+types/api.boxes.$deviceId.$sensorId'
import { postSingleMeasurement } from '~/lib/measurement-service.server'
import { isValidServiceKey } from '~/models/integration.server'
import { StandardResponse } from '~/utils/response-utils'

export const action: ActionFunction = async ({
export const action = async ({
request,
params,
}: ActionFunctionArgs): Promise<Response> => {
}: Route.ActionArgs): Promise<Response> => {
try {
const { deviceId, sensorId } = params

Expand Down Expand Up @@ -57,10 +57,12 @@ export const action: ActionFunction = async ({
(err.name === 'ModelError' && err.type === 'UnprocessableEntityError')
)
return StandardResponse.unprocessableContent(err.message)

if (err.name === 'ArchivedDeviceError')
return new Response(
JSON.stringify({ message: err.message || 'Archived devices are read-only' }),
JSON.stringify({
message: err.message || 'Archived devices are read-only',
}),
{
status: 409,
headers: { 'Content-Type': 'application/json; charset=utf-8' },
Expand Down
5 changes: 3 additions & 2 deletions app/routes/api.boxes.$deviceId.compile.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { type ActionFunction, type ActionFunctionArgs } from 'react-router'
import { type ActionFunction } from 'react-router'
import { type Route } from './+types/api.boxes.$deviceId.compile'

const COMPILER_URL = 'https://compiler.sensebox.de/compile'

export const action: ActionFunction = async ({
request,
params,
}: ActionFunctionArgs): Promise<Response> => {
}: Route.ActionArgs): Promise<Response> => {
const { deviceId } = params
if (!deviceId) {
return Response.json(
Expand Down
6 changes: 3 additions & 3 deletions app/routes/api.boxes.$deviceId.data.$sensorId.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
type Params,
type LoaderFunction,
type LoaderFunctionArgs,
type LoaderFunction
} from 'react-router'
import { type Route } from './+types/api.boxes.$deviceId.data.$sensorId'
import {
type TransformedMeasurement,
transformOutliers,
Expand Down Expand Up @@ -148,7 +148,7 @@ import { StandardResponse } from '~/utils/response-utils'
export const loader: LoaderFunction = async ({
request,
params,
}: LoaderFunctionArgs): Promise<Response> => {
}: Route.LoaderArgs): Promise<Response> => {
try {
const collected = collectParameters(request, params)
if (collected instanceof Response) return collected
Expand Down
10 changes: 6 additions & 4 deletions app/routes/api.boxes.$deviceId.data.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type ActionFunction, type ActionFunctionArgs } from 'react-router'
import { type Route } from './+types/api.boxes.$deviceId.data'
import { postNewMeasurements } from '~/lib/measurement-service.server'
import { isValidServiceKey } from '~/models/integration.server'
import { StandardResponse } from '~/utils/response-utils'
Expand All @@ -18,10 +18,10 @@ import { StandardResponse } from '~/utils/response-utils'
* type: string
* description: alternative HTTP header for authorizing your device if you cannot use the HTTP Authorization header
*/
export const action: ActionFunction = async ({
export const action = async ({
request,
params,
}: ActionFunctionArgs): Promise<Response> => {
}: Route.ActionArgs): Promise<Response> => {
try {
const deviceId = params.deviceId
if (deviceId === undefined)
Expand Down Expand Up @@ -77,7 +77,9 @@ export const action: ActionFunction = async ({

if (err.name === 'ArchivedDeviceError')
return new Response(
JSON.stringify({ message: err.message || 'Archived devices are read-only' }),
JSON.stringify({
message: err.message || 'Archived devices are read-only',
}),
{
status: 409,
headers: { 'Content-Type': 'application/json; charset=utf-8' },
Expand Down
4 changes: 2 additions & 2 deletions app/routes/api.boxes.$deviceId.locations.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
type Params,
type LoaderFunction,
type LoaderFunctionArgs,
} from 'react-router'
import { type Route } from './+types/api.boxes.$deviceId.locations'
import { getLocations } from '~/models/device.server'
import { parseDateParam, parseEnumParam } from '~/utils/param-utils'
import { StandardResponse } from '~/utils/response-utils'
Expand Down Expand Up @@ -98,7 +98,7 @@ import { StandardResponse } from '~/utils/response-utils'
export const loader: LoaderFunction = async ({
request,
params,
}: LoaderFunctionArgs): Promise<Response> => {
}: Route.LoaderArgs): Promise<Response> => {
try {
const collected = collectParameters(request, params)
if (collected instanceof Response) return collected
Expand Down
Loading