-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Fix <Edit>, <ReferenceField> and <List> to better support offline mode
#11161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
4b60676
Add an offline example
djhi 2e6440f
update offline config according to doc
slax57 27c6538
Merge remote-tracking branch 'origin/master' into offline-example
slax57 9a5133c
disable redirectOnError in PostEdit
slax57 a95ae3d
fix redirectOnError
slax57 05d2c5b
remove console.log
slax57 20a1e6c
revert package json files
slax57 02fd89a
fix mutations
slax57 219d1a5
add offline example scripts to Makefile and package.json
slax57 c6f5ed1
yarn dedupe
slax57 eca9991
remove ra packages duplicates
slax57 dcc20bc
upgrade to codeql v3
slax57 e40df52
manually fix yarn.lock
slax57 ca9d516
improve demo readme
slax57 3a6eb4c
remove unnecessary deps
slax57 eec1044
add tanstack query devtools
slax57 7c5a208
replace PostList by ListGuesser
slax57 49012c2
simplify index.html
slax57 974d9b9
cleanup unnecessary deps
slax57 5acd057
code review
slax57 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Logs | ||
| logs | ||
| *.log | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
| pnpm-debug.log* | ||
| lerna-debug.log* | ||
|
|
||
| node_modules | ||
| dist | ||
| dist-ssr | ||
| *.local | ||
|
|
||
| # Editor directories and files | ||
| .vscode/* | ||
| !.vscode/extensions.json | ||
| .idea | ||
| .DS_Store | ||
| *.suo | ||
| *.ntvs* | ||
| *.njsproj | ||
| *.sln | ||
| *.sw? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # ra-offline | ||
|
|
||
| Demo app showing the React-Admin offline-first capabilities. | ||
|
|
||
| It uses [vite-plugin-pwa](https://vite-pwa-org.netlify.app/) to make the app a Progressive Web App, and [configures the TanStack QueryClient](https://marmelab.com/react-admin/DataProviders.html#offline-support) to persist the query cache and pending mutations in the local storage. | ||
|
|
||
| ## Installation | ||
|
|
||
| Install the application dependencies by running: | ||
|
|
||
| ```sh | ||
| npm install | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| The offline mode doesn't work in dev mode, that's a limitation of vite-pwa. | ||
|
|
||
| Build the application in production mode and serve it by running: | ||
|
|
||
| ```sh | ||
| npm run build | ||
| npm run preview | ||
| ``` | ||
|
|
||
| Use the Browser DevTools (or phone Airplane mode) to simulate Offline mode when needed. Using TanStack Query DevTools does not work. | ||
|
|
||
| ## Limitations | ||
|
|
||
| This demo is hooked up to the [JSONPlaceholder](https://jsonplaceholder.typicode.com/) API, so the changes are not persisted for real. But the mutation should be visible in the Network tab and not trigger errors. | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| if ("serviceWorker" in navigator) | ||
| navigator.serviceWorker.register("/dev-sw.js?dev-sw", { | ||
| scope: "/", | ||
| type: "module", | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import js from "@eslint/js"; | ||
| import { defineConfig, globalIgnores } from "eslint/config"; | ||
| import tseslint from "typescript-eslint"; | ||
| import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; | ||
| import react from "eslint-plugin-react"; | ||
| import reactHooks from "eslint-plugin-react-hooks"; | ||
| import globals from "globals"; | ||
|
|
||
| export default defineConfig([ | ||
| globalIgnores(["**/node_modules", "**/dist"]), | ||
| { | ||
| name: "eslint-js-recommended-rules", | ||
| plugins: { | ||
| js, | ||
| }, | ||
| extends: ["js/recommended"], | ||
| }, | ||
| tseslint.configs.recommended.map((conf) => ({ | ||
| ...conf, | ||
| files: ["**/*.ts", "**/*.tsx"], | ||
| })), | ||
| eslintPluginPrettierRecommended, | ||
| { | ||
| name: "react", | ||
| ...react.configs.flat.recommended, | ||
| }, | ||
| reactHooks.configs["recommended-latest"], | ||
| { | ||
| languageOptions: { | ||
| globals: { | ||
| ...globals.browser, | ||
| ...globals.node, | ||
| }, | ||
| }, | ||
| rules: { | ||
| "react/react-in-jsx-scope": "off", | ||
| }, | ||
| settings: { | ||
| react: { | ||
| version: "detect", | ||
| }, | ||
| }, | ||
| }, | ||
| ]); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8" /> | ||
| <meta name="viewport" content="width=device-width,initial-scale=1" /> | ||
| <title>React-Admin Offline</title> | ||
| <meta name="description" content="React-Admin Offline Demo" /> | ||
| <link rel="icon" href="/favicon.ico" /> | ||
| <link rel="apple-touch-icon" href="/apple-touch-icon-180x180.png" sizes="180x180" /> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can simplify by removing the favicons and loading css |
||
| <link rel="mask-icon" href="/maskable-icon-512x512.png" color="#FFFFFF" /> | ||
| <meta name="theme-color" content="#ffffff" /> | ||
| <link rel="preconnect" href="https://fonts.gstatic.com" /> | ||
| <link | ||
| href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" | ||
| rel="stylesheet" | ||
| /> | ||
| </head> | ||
|
|
||
| <body> | ||
| <noscript> You need to enable JavaScript to run this app. </noscript> | ||
| <div id="root"></div> | ||
| </body> | ||
| <script type="module" src="/src/index.tsx"></script> | ||
| </html> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| { | ||
| "private": true, | ||
| "type": "module", | ||
| "scripts": { | ||
| "dev": "vite", | ||
| "build": "vite build", | ||
| "preview": "vite preview", | ||
| "type-check": "tsc --noEmit", | ||
| "lint": "eslint --fix --ext .js,.jsx,.ts,.tsx ./src", | ||
| "format": "prettier --write ./src" | ||
| }, | ||
| "dependencies": { | ||
| "@emotion/react": "^11.14.0", | ||
| "@emotion/styled": "^11.14.0", | ||
| "@mui/icons-material": "^7.0.1", | ||
| "@mui/material": "^7.0.1", | ||
| "@tanstack/query-async-storage-persister": "^5.90.22", | ||
| "@tanstack/react-query": "^5.90.21", | ||
| "@tanstack/react-query-devtools": "^5.90.22", | ||
| "@tanstack/react-query-persist-client": "^5.90.22", | ||
| "ra-data-json-server": "^5.14.1", | ||
| "react": "^19.0.0", | ||
| "react-admin": "^5.14.1", | ||
| "react-dom": "^19.0.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@eslint/js": "^9.23.0", | ||
| "@types/node": "^20.10.7", | ||
| "@types/react": "^18.3.3", | ||
| "@types/react-dom": "^18.3.0", | ||
| "@vitejs/plugin-react": "^4.3.4", | ||
| "eslint": "^9.23.0", | ||
| "eslint-config-prettier": "^10.1.1", | ||
| "eslint-plugin-prettier": "^5.2.5", | ||
| "eslint-plugin-react": "^7.37.4", | ||
| "eslint-plugin-react-hooks": "^5.2.0", | ||
| "globals": "^16.0.0", | ||
| "prettier": "^3.3.3", | ||
| "typescript": "^5.1.6", | ||
| "typescript-eslint": "^8.28.0", | ||
| "vite": "^6.2.6", | ||
| "vite-plugin-pwa": "^1.2.0" | ||
| }, | ||
| "name": "ra-offline" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default {}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| User-agent: * | ||
| Allow: / |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import { | ||
| Admin, | ||
| Resource, | ||
| addOfflineSupportToQueryClient, | ||
| ListGuesser, | ||
| } from "react-admin"; | ||
| import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"; | ||
| import { createAsyncStoragePersister } from "@tanstack/query-async-storage-persister"; | ||
| import jsonDataProvider from "ra-data-json-server"; | ||
| import { QueryClient } from "@tanstack/react-query"; | ||
| import { Layout } from "./Layout"; | ||
| import { PostEdit } from "./PostEdit"; | ||
|
|
||
| const dataProvider = jsonDataProvider("https://jsonplaceholder.typicode.com"); | ||
|
|
||
| const baseQueryClient = new QueryClient({ | ||
| defaultOptions: { | ||
| queries: { | ||
| gcTime: 1000 * 60 * 60 * 24, // 24 hours | ||
| networkMode: "offlineFirst", | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| export const queryClient = addOfflineSupportToQueryClient({ | ||
| queryClient: baseQueryClient, | ||
| dataProvider, | ||
| resources: ["posts", "comments", "users"], | ||
| }); | ||
|
|
||
| const localStoragePersister = createAsyncStoragePersister({ | ||
| storage: window.localStorage, | ||
| }); | ||
|
|
||
| export const App = () => ( | ||
| <PersistQueryClientProvider | ||
| client={queryClient} | ||
| persistOptions={{ persister: localStoragePersister }} | ||
| onSuccess={() => { | ||
| // resume mutations after initial restore from localStorage is successful | ||
| queryClient.resumePausedMutations(); | ||
| }} | ||
| > | ||
| <Admin | ||
| layout={Layout} | ||
| dataProvider={dataProvider} | ||
| queryClient={queryClient} | ||
| disableTelemetry | ||
| > | ||
| <Resource name="posts" list={ListGuesser} edit={PostEdit} /> | ||
| </Admin> | ||
| </PersistQueryClientProvider> | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import type { ReactNode } from "react"; | ||
| import { Layout as RALayout } from "react-admin"; | ||
| import { ReactQueryDevtools } from "@tanstack/react-query-devtools/production"; | ||
|
|
||
| export const Layout = ({ children }: { children: ReactNode }) => ( | ||
| <RALayout> | ||
| {children} | ||
| <ReactQueryDevtools initialIsOpen={false} /> | ||
| </RALayout> | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { Edit, ReferenceInput, SimpleForm, TextInput } from "react-admin"; | ||
|
|
||
| export const PostEdit = () => ( | ||
| <Edit redirectOnError={false}> | ||
| <SimpleForm> | ||
| <ReferenceInput source="userId" reference="users" /> | ||
| <TextInput source="id" /> | ||
| <TextInput source="title" /> | ||
| <TextInput source="body" /> | ||
| </SimpleForm> | ||
| </Edit> | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import React from "react"; | ||
| import ReactDOM from "react-dom/client"; | ||
| import { App } from "./App"; | ||
|
|
||
| ReactDOM.createRoot(document.getElementById("root")!).render( | ||
| <React.StrictMode> | ||
| <App /> | ||
| </React.StrictMode>, | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { | ||
| cleanupOutdatedCaches, | ||
| createHandlerBoundToURL, | ||
| precacheAndRoute, | ||
| } from "workbox-precaching"; | ||
| import { NavigationRoute, registerRoute } from "workbox-routing"; | ||
|
|
||
| declare let self: ServiceWorkerGlobalScope; | ||
|
|
||
| self.addEventListener("message", (event) => { | ||
| if (event.data && event.data.type === "SKIP_WAITING") self.skipWaiting(); | ||
| }); | ||
|
|
||
| // self.__WB_MANIFEST is default injection point | ||
| precacheAndRoute(self.__WB_MANIFEST); | ||
|
|
||
| // clean old assets | ||
| cleanupOutdatedCaches(); | ||
|
|
||
| // to allow work offline | ||
| registerRoute(new NavigationRoute(createHandlerBoundToURL("index.html"))); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| /// <reference types="vite/client" /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "composite": true, | ||
| "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", | ||
| "target": "ES2020", | ||
| "useDefineForClassFields": true, | ||
| "lib": ["ES2020", "DOM", "DOM.Iterable"], | ||
| "module": "ESNext", | ||
| "skipLibCheck": true, | ||
|
|
||
| /* Bundler mode */ | ||
| "moduleResolution": "bundler", | ||
| "allowImportingTsExtensions": true, | ||
| "resolveJsonModule": true, | ||
| "isolatedModules": true, | ||
| "moduleDetection": "force", | ||
| "noEmit": true, | ||
| "jsx": "react-jsx", | ||
|
|
||
| /* Linting */ | ||
| "strict": true, | ||
| "noUnusedLocals": true, | ||
| "noUnusedParameters": true, | ||
| "noFallthroughCasesInSwitch": true | ||
| }, | ||
| "include": ["src"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "files": [], | ||
| "references": [ | ||
| { | ||
| "path": "./tsconfig.app.json" | ||
| }, | ||
| { | ||
| "path": "./tsconfig.node.json" | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "composite": true, | ||
| "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", | ||
| "skipLibCheck": true, | ||
| "module": "ESNext", | ||
| "moduleResolution": "bundler", | ||
| "allowSyntheticDefaultImports": true, | ||
| "strict": true, | ||
| "noEmit": true | ||
| }, | ||
| "include": ["vite.config.ts"] | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deserves a one line explanation of the demo puropse and usage