Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fe47878
Migrate from Create React App to Vite
ankit0504 Apr 20, 2026
3af67a1
Fix 55 lint errors surfaced by removing CRA's react-app preset
ankit0504 Apr 20, 2026
63edc16
Define process.env shim for Vite
ankit0504 Apr 22, 2026
60ac98c
Address PR review: rename vite config, replace Link with Button
ankit0504 Apr 27, 2026
f509fd6
Upgrade React to 17.0.2 and associated types to 17
ankit0504 Apr 21, 2026
f7bf521
Run @mui/codemod v5 preset-safe and swap @material-ui for @mui
ankit0504 Apr 28, 2026
6e6b8c6
Replace react-swipeable-views with plain tab panels
ankit0504 Apr 28, 2026
61f4a7a
Replace material-table with MUI X Data Grid
ankit0504 Apr 28, 2026
39edc0e
Fix MUI v5 API breakages so the build passes
ankit0504 Apr 28, 2026
674688b
Wire CSV/PDF export back into the table toolbar and add Filters/Colum…
ankit0504 Apr 28, 2026
a97713e
Auto-size table rows so multi-value cells render fully
ankit0504 Apr 28, 2026
6182302
Align "Has media" checkbox with the rest of the filter row
ankit0504 Apr 28, 2026
6619cb9
Replace @mui/x-data-grid with @tanstack/react-table
ankit0504 Apr 28, 2026
37084e7
Coerce undefined cell values to empty strings
ankit0504 Apr 28, 2026
51fe9af
Drop the redundant "Has" label next to Audio/Video filter checkboxes
ankit0504 Apr 28, 2026
1c98abb
Exclude hidden columns from CSV/PDF exports
ankit0504 Apr 28, 2026
ec87b66
Migrate react-query v2 to TanStack Query v4
ankit0504 Apr 28, 2026
0688d29
Migrate react-router-dom 5 to 6
ankit0504 Apr 28, 2026
2be76b2
Upgrade react-map-gl to v7 and replace react-map-gl-geocoder
ankit0504 Apr 28, 2026
b3ccd2c
Wrap two stragglers in Routes / convert to useMatch
ankit0504 Apr 28, 2026
320fa88
Move React Query Devtools toggle to the bottom-right
ankit0504 Apr 28, 2026
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
10 changes: 7 additions & 3 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"extends": [
"airbnb-typescript",
"airbnb/hooks",
"react-app",
"prettier/react",
"plugin:jest/recommended",
"plugin:react/recommended",
Expand All @@ -40,7 +39,12 @@
// last configuration in the extends array.
"plugin:prettier/recommended"
],
"ignorePatterns": ["scratch", "src/serviceWorker.ts", "build"],
"ignorePatterns": [
"scratch",
"build",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
"rules": {
"array-bracket-newline": [
"error",
Expand Down Expand Up @@ -178,6 +182,6 @@
"import/newline-after-import": "error",
"import/extensions": 0,
"import/prefer-default-export": 0,
"@typescript-eslint/no-unused-vars": ["error"]
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }]
}
}
22 changes: 7 additions & 15 deletions public/index.html → index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<!-- End Google Tag Manager -->
<meta charset="utf-8" />
<!-- CRED: favicon stuff: https://realfavicongenerator.net/ -->
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32x32.png?v=2.1">
<link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/favicon-16x16.png?v=2.1">
<link rel="icon" href="%PUBLIC_URL%/favicon.ico?v=2.1" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png?v=2.1">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png?v=2.1">
<link rel="icon" href="/favicon.ico?v=2.1" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#ffffff" />
<meta name="apple-mobile-web-app-title" content="Languages of NYC">
Expand All @@ -29,7 +29,7 @@
name="description"
content="An interactive language diversity map of New York City"
/>
<link rel="apple-touch-icon" sizes="180x180" href="%PUBLIC_URL%/apple-touch-icon.png?v=2.2">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=2.2">
<meta property="og:title" content="Languages of New York City Map" />
<meta property="og:site_name" content="Languages of New York City Map" />
<meta property="og:url" content="https://languagemap.nyc/" />
Expand All @@ -56,17 +56,8 @@
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json?v=2.1" />
<link rel="mask-icon" href="%PUBLIC_URL%/safari-pinned-tab.svg?v=2.1" color="#379587">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<link rel="manifest" href="/manifest.json?v=2.1" />
<link rel="mask-icon" href="/safari-pinned-tab.svg?v=2.1" color="#379587">
<title>Languages of New York City</title>
</head>
<body>
Expand All @@ -82,6 +73,7 @@
<!-- End Google Tag Manager (noscript) -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
<script>
const earlyAccessPath = 'https://fonts.googleapis.com/earlyaccess/'
Expand Down
71 changes: 35 additions & 36 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,55 +3,62 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.10.2",
"@material-ui/lab": "^4.0.0-alpha.56",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mapbox/mapbox-gl-geocoder": "^5.1.2",
"@math.gl/web-mercator": "^4.1.0",
"@mui/lab": "^5.0.0-alpha.176",
"@mui/material": "^5.16.7",
"@mui/styles": "^5.16.7",
"@sentry/react": "^5.24.2",
"@tanstack/react-query": "^4",
"@tanstack/react-query-devtools": "^4",
"@tanstack/react-table": "^8.21.3",
"@testing-library/jest-dom": "^5.11.0",
"@testing-library/react": "^10.4.5",
"@testing-library/user-event": "^7.1.2",
"@types/geojson": "^7946.0.7",
"@types/jest": "^24.0.0",
"@types/match-sorter": "^4.0.0",
"@types/node": "^14.0.13",
"@types/react": "^16.9.35",
"@types/react-dom": "^16.9.8",
"@types/react": "^17.0.83",
"@types/react-dom": "^17.0.26",
"@types/react-map-gl": "^5.2.7",
"@types/react-router-dom": "^5.1.5",
"@types/react-swipeable-views": "^0.13.0",
"@types/react-window": "^1.8.2",
"@types/webfontloader": "^1.6.32",
"airtable": "^0.10.1",
"clsx": "^1.1.1",
"filefy": "^0.1.10",
"history": "^5.0.0",
"jest-canvas-mock": "^2.2.0",
"jspdf": "^2.1.0",
"jspdf-autotable": "^3.5.13",
"mapbox-gl": "^1.11.1",
"match-sorter": "^4.2.0",
"material-table": "1.68.1",
"react": "^16.14.0",
"react": "^17.0.2",
"react-device-detect": "^1.17.0",
"react-dom": "^16.14.0",
"react-dom": "^17.0.2",
"react-icons": "^4.2.0",
"react-map-gl": "^5.2.7",
"react-map-gl-geocoder": "^2.0.16",
"react-map-gl": "^7",
"react-markdown": "^5.0.3",
"react-query": "^2.12.1",
"react-query-devtools": "^2.6.3",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1",
"react-router-dom": "^6",
"react-share": "^4.2.1",
"react-swipeable-views": "^0.13.9",
"react-transition-group": "^4.4.1",
"react-window": "^1.8.5",
"simple-statistics": "^7.3.2",
"typescript": "4.9.5",
"webfontloader": "^1.6.28"
},
"devDependencies": {
"@types/mapbox__mapbox-gl-geocoder": "^5.1.1",
"@typescript-eslint/eslint-plugin": "^3.6.0",
"@typescript-eslint/parser": "^3.6.0",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^7.32.0",
"eslint-config-airbnb": "^18.2.0",
"eslint-config-airbnb-typescript": "^8.0.2",
"eslint-config-prettier": "^6.11.0",
"eslint-config-react-app": "^5.2.1",
"eslint-import-resolver-typescript": "^2.0.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-flowtype": "^5.2.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jest": "^23.18.0",
Expand All @@ -64,18 +71,17 @@
"lint-staged": "^10.2.11",
"prettier": "^2.0.5",
"prettier-eslint": "^11.0.0",
"prettier-eslint-cli": "^5.0.0"
"prettier-eslint-cli": "^5.0.0",
"vite": "^6.0.7",
"vite-plugin-svgr": "^4.3.0",
"vite-tsconfig-paths": "^5.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jest-environment-jsdom-sixteen",
"eject": "react-scripts eject",
"start": "vite",
"build": "tsc --noEmit && vite build",
"preview": "vite preview",
"lint": "eslint '*/**/*.{js,ts,tsx}' --quiet"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
Expand All @@ -88,15 +94,6 @@
"last 1 safari version"
]
},
"peerDependencies": {
"@material-ui/styles": "^4.10.0",
"clsx": "^1.1.1",
"filefy": "^0.1.10",
"history": "^5.0.0",
"jspdf": "^2.1.0",
"jspdf-autotable": "^3.5.13",
"mapbox-gl": "^1.11.1"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
Expand All @@ -107,6 +104,8 @@
},
"resolutions": {
"material-table/jspdf": "^2.1.0",
"material-table/jspdf-autotable": "^3.5.13"
"material-table/jspdf-autotable": "^3.5.13",
"@types/react": "^17.0.83",
"@types/react-dom": "^17.0.26"
}
}
36 changes: 16 additions & 20 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import React, { FC } from 'react'
import * as Sentry from '@sentry/react'
// import { ReactQueryDevtools } from 'react-query-devtools'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import Airtable from 'airtable'

import { AIRTABLE_API_KEY } from 'components/config'
import { AIRTABLE_API_KEY, reactQueryDefaults } from 'components/config'
import { PanelContextProvider } from 'components/panels'
import { ResultsModal } from 'components/results'
import { AppWrap } from './AppWrap'
import { MapToolsProvider } from './context/MapToolsContext'

// // Provide the default query function to your app with defaultConfig
// const mainQueryCache = new QueryCache({
// defaultConfig: {
// queries: {
// queryFn: asyncAwaitFetch,
// refetchOnMount: false,
// cacheTime: 1800000, // 1000 * 60 * 30, // ms * sec * min. Default: 5 min.
// },
// },
// })
const queryClient = new QueryClient({
defaultOptions: { queries: reactQueryDefaults },
})

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // great start 🙄
Expand All @@ -43,14 +37,16 @@ export const App: FC = () => {
</>
)}
>
<MapToolsProvider>
<PanelContextProvider>
<AppWrap />
</PanelContextProvider>
{/* TODO: make Suspense/Lazy work on poor connections */}
<ResultsModal />
</MapToolsProvider>
{/* <ReactQueryDevtools /> */}
<QueryClientProvider client={queryClient}>
<MapToolsProvider>
<PanelContextProvider>
<AppWrap />
</PanelContextProvider>
{/* TODO: make Suspense/Lazy work on poor connections */}
<ResultsModal />
</MapToolsProvider>
{import.meta.env.DEV && <ReactQueryDevtools position="bottom-right" />}
</QueryClientProvider>
</Sentry.ErrorBoundary>
)
}
12 changes: 7 additions & 5 deletions src/components/AppWrap.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { FC, useState } from 'react'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import { InteractiveMap } from 'react-map-gl'
import { Hidden } from '@material-ui/core'
import { Theme } from '@mui/material/styles'
import createStyles from '@mui/styles/createStyles'
import makeStyles from '@mui/styles/makeStyles'
import { MapRef } from 'react-map-gl'
import { Hidden } from '@mui/material'

import { panelWidths } from 'components/panels/config'
import { PanelWrap, usePanelState, ShowPanelBtn } from 'components/panels'
Expand Down Expand Up @@ -45,7 +47,7 @@ const useStyles = makeStyles((theme: Theme) =>
[theme.breakpoints.up('xl')]: {
left: (props: Style) => (props.open ? panelWidths.midLarge : 0),
},
[theme.breakpoints.down('sm')]: {
[theme.breakpoints.down('md')]: {
top: PANEL_TITLE_BAR_HT_MOBILE,
width: '100%',
bottom: (props: Style) =>
Expand All @@ -67,7 +69,7 @@ export const AppWrap: FC = () => {
const [mapLoaded, setMapLoaded] = useState<boolean>(false)
const { panelOpen } = usePanelState()
const classes = useStyles({ open: panelOpen })
const mapRef: React.RefObject<InteractiveMap> = React.useRef(null)
const mapRef: React.RefObject<MapRef> = React.useRef(null)
const showWelcome = useShowWelcome()

usePageTitle()
Expand Down
16 changes: 10 additions & 6 deletions src/components/about/AboutPageView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, { FC } from 'react'
import { useQuery } from 'react-query'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import { useQuery } from '@tanstack/react-query'
import { Theme } from '@mui/material/styles'

import createStyles from '@mui/styles/createStyles'
import makeStyles from '@mui/styles/makeStyles'

import { LoadingIndicator } from 'components/generic/modals'
import { AboutPageProps, WpApiPageResponse } from './types'
Expand All @@ -19,7 +22,7 @@ const useStyles = makeStyles((theme: Theme) =>
boxShadow: theme.shadows[8],
// Prevent screenshots from getting lost in Paper bg if same color:
// outline: 'solid 1px hsl(0deg 0% 40%)',
[theme.breakpoints.down('xs')]: {
[theme.breakpoints.down('sm')]: {
margin: '0.5rem 0',
},
},
Expand All @@ -38,9 +41,10 @@ export const AboutPageView: FC<AboutPageProps> = (props) => {
const { queryKey, noImgShadow } = props
const classes = useStyles()

const { data, isLoading, error } = useQuery(queryKey, () =>
defaultQueryFn<WpApiPageResponse>(queryKey)
)
const { data, isLoading, error } = useQuery<WpApiPageResponse>({
queryKey: [queryKey],
queryFn: () => defaultQueryFn<WpApiPageResponse>(queryKey),
})

if (isLoading) return <LoadingIndicator omitText />

Expand Down
5 changes: 4 additions & 1 deletion src/components/about/FeedbackForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React, { FC } from 'react'
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
import { Theme } from '@mui/material/styles'

import makeStyles from '@mui/styles/makeStyles'
import createStyles from '@mui/styles/createStyles'

const useStyles = makeStyles((theme: Theme) =>
createStyles({
Expand Down
5 changes: 4 additions & 1 deletion src/components/about/FeedbackModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React, { FC } from 'react'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import { Theme } from '@mui/material/styles'

import createStyles from '@mui/styles/createStyles'
import makeStyles from '@mui/styles/makeStyles'

import { SimpleDialog } from 'components/generic/modals'
import { FeedbackForm } from 'components/about'
Expand Down
6 changes: 4 additions & 2 deletions src/components/about/FeedbackToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { FC, useState } from 'react'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import { Button } from '@material-ui/core'
import { Theme } from '@mui/material/styles'
import createStyles from '@mui/styles/createStyles'
import makeStyles from '@mui/styles/makeStyles'
import { Button } from '@mui/material'

import { FeedbackModal } from 'components/about'
import { Explanation, UItextFromAirtable } from 'components/generic'
Expand Down
Loading