import * as React from 'react';
import { useState } from 'react';
import { QueryClient, useIsMutating } from '@tanstack/react-query';
import fakeRestDataProvider from 'ra-data-fakerest';
import { CoreAdmin, CoreAdminContext, Resource } from '../core';
import { useUpdate } from './useUpdate';
import { useGetOne } from './useGetOne';
import type { MutationMode as MutationModeType } from '../types';
import {
EditBase,
ListBase,
RecordsIterator,
useRegisterMutationMiddleware,
} from '../controller';
import { Form, InputProps, useInput } from '../form';
import { TestMemoryRouter, LinkBase } from '../routing';
import { testDataProvider } from './testDataProvider';
import { useNotificationContext } from '../notification';
import { useTakeUndoableMutation } from './undo';
export default { title: 'ra-core/dataProvider/useUpdate' };
export const MutationMode = ({ timeout = 1000 }) => {
const posts = [{ id: 1, title: 'Hello', author: 'John Doe' }];
const dataProvider = {
getOne: (resource, params) => {
return Promise.resolve({
data: posts.find(p => p.id === params.id),
});
},
update: (resource, params) => {
return new Promise(resolve => {
setTimeout(() => {
const post = posts.find(p => p.id === params.id);
if (post) {
post.title = params.data.title;
}
resolve({ data: post });
}, timeout);
});
},
} as any;
return (
);
};
const MutationModeCore = () => {
const isMutating = useIsMutating();
const [success, setSuccess] = useState();
const { data, refetch } = useGetOne('posts', { id: 1 });
const [mutationMode, setMutationMode] =
React.useState('pessimistic');
const [update, { isPending }] = useUpdate(
'posts',
{
id: 1,
data: { title: 'Hello World' },
},
{
mutationMode,
onSuccess: () => setSuccess('success'),
}
);
const handleClick = () => {
update();
};
return (
<>
- title
- {data?.title}
- author
- {data?.author}
{success && {success}
}
{isMutating !== 0 && mutating
}
>
);
};
export const Params = ({ timeout = 1000 }) => {
const posts = [{ id: 1, title: 'Hello', author: 'John Doe' }];
const dataProvider = {
getOne: (resource, params) => {
return Promise.resolve({
data: posts.find(p => p.id === params.id),
});
},
update: (resource, params) => {
return new Promise(resolve => {
setTimeout(() => {
const post = posts.find(p => p.id === params.id);
if (post) {
post.title = params.data.title;
}
resolve({ data: post });
}, timeout);
});
},
} as any;
return (
);
};
const ParamsCore = () => {
const isMutating = useIsMutating();
const [success, setSuccess] = useState();
const { data, refetch } = useGetOne('posts', { id: 1 });
const [params, setParams] = React.useState({ title: 'Hello World' });
const [update, { isPending }] = useUpdate(
'posts',
{
id: 1,
data: params,
},
{
mutationMode: 'optimistic',
onSuccess: () => setSuccess('success'),
}
);
const handleClick = () => {
update();
};
return (
<>
- title
- {data?.title}
- author
- {data?.author}
{success && {success}
}
{isMutating !== 0 && mutating
}
>
);
};
export const Middleware = ({
middleware = (resource: string, params: any) => {
console.log(
`Updating resource ${resource} with params:`,
JSON.stringify(params)
);
},
mutationMode = 'undoable',
timeout = 1000,
}: {
mutationMode?: MutationModeType;
timeout?: number;
middleware?: (resource: string, params: any) => void;
}) => {
const posts = [{ id: 1, title: 'Hello', author: 'John Doe' }];
const dataProvider = testDataProvider({
// @ts-ignore
getList: () => {
return Promise.resolve({
data: posts,
total: posts.length,
});
},
// @ts-ignore
getOne: (resource, params) => {
return Promise.resolve({
// eslint-disable-next-line eqeqeq
data: posts.find(p => p.id == params.id),
});
},
update: (resource, params) => {
return new Promise(resolve => {
setTimeout(() => {
// eslint-disable-next-line eqeqeq
const post = posts.find(p => p.id == params.id);
if (post) {
post.title = params.data.title;
}
// @ts-ignore
resolve({ data: post });
}, timeout);
});
},
});
return (
(
<>
{children}
>
)}
>
}
edit={
}
/>
);
};
Middleware.args = {
timeout: 1000,
mutationMode: 'optimistic',
};
Middleware.argTypes = {
timeout: {
control: {
type: 'number',
},
},
mutationMode: {
control: {
type: 'select',
},
options: ['pessimistic', 'optimistic', 'undoable'],
},
};
const UpdateMiddleware = ({
middleware,
}: {
middleware: (resource: string, params: any) => void;
}) => {
useRegisterMutationMiddleware((resource, params, next) => {
middleware(resource, params);
return next(resource, params);
});
return null;
};
const Notification = () => {
const { notifications, resetNotifications } = useNotificationContext();
const takeMutation = useTakeUndoableMutation();
return notifications.length > 0 ? (
<>
{notifications[0].message}
>
) : null;
};
const TextInput = (props: InputProps) => {
const { field, id } = useInput(props);
return (
);
};
export const InvalidateList = ({
mutationMode = 'undoable',
}: {
mutationMode?: MutationModeType;
}) => {
const dataProvider = fakeRestDataProvider(
{
posts: [
{ id: 1, title: 'Hello' },
{ id: 2, title: 'World' },
],
},
process.env.NODE_ENV !== 'test',
process.env.NODE_ENV === 'test' ? 10 : 1000
);
return (
Loading...
}>
(
{record.id}: {record.title}
)}
/>
}
edit={
}
/>
);
};
InvalidateList.args = {
mutationMode: 'undoable',
};
InvalidateList.argTypes = {
mutationMode: {
control: {
type: 'select',
},
options: ['pessimistic', 'optimistic', 'undoable'],
},
};