@@ -6,18 +6,29 @@ import {
66 useRecordContext ,
77 TestMemoryRouter ,
88 useEditContext ,
9+ IsOffline ,
910} from 'ra-core' ;
1011import polyglotI18nProvider from 'ra-i18n-polyglot' ;
1112import englishMessages from 'ra-language-english' ;
12- import { Box , Card , Stack , ThemeOptions , Typography } from '@mui/material' ;
13+ import fakeRestDataProvider from 'ra-data-fakerest' ;
14+
15+ import {
16+ Alert ,
17+ Box ,
18+ Card ,
19+ Stack ,
20+ ThemeOptions ,
21+ Typography ,
22+ } from '@mui/material' ;
1323
1424import { TextInput } from '../input' ;
1525import { SimpleForm } from '../form/SimpleForm' ;
1626import { ShowButton , SaveButton } from '../button' ;
1727import TopToolbar from '../layout/TopToolbar' ;
18- import { Edit } from './Edit' ;
28+ import { Edit , EditProps } from './Edit' ;
1929import { deepmerge } from '@mui/utils' ;
2030import { defaultLightTheme } from '../theme' ;
31+ import { onlineManager , useMutationState } from '@tanstack/react-query' ;
2132
2233export default { title : 'ra-ui-materialui/detail/Edit' } ;
2334
@@ -30,9 +41,9 @@ const book = {
3041 year : 1869 ,
3142} ;
3243
33- const dataProvider = {
34- getOne : ( ) => Promise . resolve ( { data : book } ) ,
35- } as any ;
44+ const dataProvider = fakeRestDataProvider ( {
45+ books : [ book ] ,
46+ } ) ;
3647
3748const BookTitle = ( ) => {
3849 const record = useRecordContext ( ) ;
@@ -418,3 +429,91 @@ export const WithRenderProp = () => (
418429 </ Admin >
419430 </ TestMemoryRouter >
420431) ;
432+
433+ export const Offline = ( {
434+ isOnline = true ,
435+ offline,
436+ } : {
437+ isOnline ?: boolean ;
438+ offline ?: React . ReactNode ;
439+ } ) => {
440+ React . useEffect ( ( ) => {
441+ onlineManager . setOnline ( isOnline ) ;
442+ } , [ isOnline ] ) ;
443+ return (
444+ < TestMemoryRouter initialEntries = { [ '/books/1/show' ] } >
445+ < Admin dataProvider = { dataProvider } >
446+ < Resource
447+ name = "books"
448+ show = { < BookEditOffline offline = { offline } /> }
449+ />
450+ </ Admin >
451+ </ TestMemoryRouter >
452+ ) ;
453+ } ;
454+
455+ const BookEditOffline = ( props : EditProps ) => {
456+ return (
457+ < Edit
458+ emptyWhileLoading
459+ { ...props }
460+ redirect = { false }
461+ mutationMode = "pessimistic"
462+ >
463+ < OfflineIndicator />
464+ < SimpleForm >
465+ < TextInput source = "title" />
466+ < TextInput source = "author" />
467+ < TextInput source = "summary" />
468+ < TextInput source = "year" />
469+ </ SimpleForm >
470+ </ Edit >
471+ ) ;
472+ } ;
473+
474+ const OfflineIndicator = ( ) => {
475+ const pendingMutations = useMutationState ( {
476+ filters : {
477+ status : 'pending' ,
478+ } ,
479+ } ) ;
480+
481+ if ( pendingMutations . length === 0 ) {
482+ return (
483+ < IsOffline >
484+ < Alert severity = "warning" >
485+ You are offline, the data may be outdated
486+ </ Alert >
487+ </ IsOffline >
488+ ) ;
489+ }
490+ return (
491+ < IsOffline >
492+ < Alert severity = "warning" > You have pending mutations</ Alert >
493+ </ IsOffline >
494+ ) ;
495+ } ;
496+
497+ const CustomOffline = ( ) => {
498+ return < Alert severity = "warning" > You are offline!</ Alert > ;
499+ } ;
500+
501+ Offline . args = {
502+ isOnline : true ,
503+ offline : 'default' ,
504+ } ;
505+
506+ Offline . argTypes = {
507+ isOnline : {
508+ control : { type : 'boolean' } ,
509+ } ,
510+ offline : {
511+ name : 'Offline component' ,
512+ control : { type : 'radio' } ,
513+ options : [ 'default' , 'custom' ] ,
514+ mapping : {
515+ default : undefined ,
516+ custom : < CustomOffline /> ,
517+ } ,
518+ } ,
519+ } ;
0 commit comments