Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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,

Check warning on line 4 in app/components/map/map.tsx

View workflow job for this annotation

GitHub Actions / ⬣ Lint

'MapEvent' is defined but never used. Allowed unused vars must match /^(_|ignored)/u
} from 'mapbox-gl'
import { forwardRef, useEffect, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
Expand All @@ -10,7 +10,7 @@
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 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 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
6 changes: 3 additions & 3 deletions app/routes/api.boxes.$deviceId.compile.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { type ActionFunction, type ActionFunctionArgs } 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 ({
export const action = async ({
request,
params,
}: ActionFunctionArgs): Promise<Response> => {
}: Route.ActionArgs): Promise<Response> => {
const { deviceId } = params
if (!deviceId) {
return Response.json(
Expand Down
11 changes: 4 additions & 7 deletions app/routes/api.boxes.$deviceId.data.$sensorId.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import {
type Params,
type LoaderFunction,
type LoaderFunctionArgs,
} from 'react-router'
import { type Params } from 'react-router'
import { type Route } from './+types/api.boxes.$deviceId.data.$sensorId'
import {
type TransformedMeasurement,
transformOutliers,
Expand Down Expand Up @@ -145,10 +142,10 @@ import { StandardResponse } from '~/utils/response-utils'
* type: string
*/

export const loader: LoaderFunction = async ({
export const loader = 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
Loading
Loading