Skip to content

Instantly share code, notes, and snippets.

@Densyakun
Last active March 10, 2023 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Densyakun/eda267d06c90f87eb160f0a331dac741 to your computer and use it in GitHub Desktop.
Save Densyakun/eda267d06c90f87eb160f0a331dac741 to your computer and use it in GitHub Desktop.
  • valtioを使ってクライアント側で管理するJSONオブジェクトの管理画面を、react-adminで実装したい
  • Data providerのra-data-fakerestは、初期化するデータにJSONデータを使用できる
  • ra-data-fakerestでは、レコードのカラムを書き換えると、渡した元のデータに反映されるが、レコードを削除しても元のデータに反映されない
  • それを可能にするためのData providerが、callbackableFakeDataProvider.tsである
  • npm i react-admin fakerest で依存関係をインストールする

TODO

  • fakerest.d.tsを書く
  • callbackableFakeDataProvider.tsを含むリポジトリを作成する
  • npmにパッケージを公開する
import * as React from "react";
import { Admin, Resource, ListGuesser, EditGuesser } from 'react-admin';
import callbackableFakeDataProvider from '@/lib/callbackableFakeDataProvider';
const App = () => {
const [data, setData] = React.useState({
"resourceName": state.value,
});
return (
<Admin
dataProvider={callbackableFakeDataProvider(data, newData => {
state.value = newData["resourceName"];
setData(newData);
})}
dashboard={Dashboard}
layout={MyLayout}
>
<Resource name="resourceName" list={ListGuesser} edit={EditGuesser} />
</Admin>
);
};
export default App;
import FakeRest from 'fakerest';
import { DataProvider } from 'ra-core';
export type Id = number | string;
export type Data = {
[key: string]: { id: Id }[]
};
export default <T extends Data>(data: T, mutate: (newData: T) => void): DataProvider => {
const restServer = new FakeRest.Server();
restServer.init(data);
if (typeof window !== 'undefined') {
// give way to update data in the console
(window as any).restServer = restServer;
}
function getResponse(type: string, resource: string, params: any) {
switch (type) {
case 'getList': {
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const query = {
sort: [field, order],
range: [(page - 1) * perPage, page * perPage - 1],
filter: params.filter,
};
return {
data: restServer.getAll(resource, query),
total: restServer.getCount(resource, {
filter: params.filter,
}),
};
}
case 'getOne':
return {
data: restServer.getOne(resource, params.id, { ...params }),
};
case 'getMany':
return {
data: restServer.getAll(resource, {
filter: { id: params.ids },
}),
};
case 'getManyReference': {
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const query = {
sort: [field, order],
range: [(page - 1) * perPage, page * perPage - 1],
filter: { ...params.filter, [params.target]: params.id },
};
return {
data: restServer.getAll(resource, query),
total: restServer.getCount(resource, {
filter: query.filter,
}),
};
}
case 'update':
return {
data: restServer.updateOne(resource, params.id, {
...params.data,
}),
};
case 'updateMany':
params.ids.forEach((id: Id) =>
restServer.updateOne(resource, id, {
...params.data,
})
);
return { data: params.ids };
case 'create':
return {
data: restServer.addOne(resource, { ...params.data }),
};
case 'delete':
return { data: restServer.removeOne(resource, params.id) };
case 'deleteMany':
params.ids.forEach((id: Id) => restServer.removeOne(resource, id));
return { data: params.ids };
default:
return false;
}
}
/**
* @param {String} type One of the data Provider methods, e.g. 'getList'
* @param {String} resource Name of the resource to fetch, e.g. 'posts'
* @param {Object} params The data request params, depending on the type
* @returns {Promise} The response
*/
const handle = (type: string, resource: string, params: any): Promise<any> => {
const collection = restServer.getCollection(resource);
if (!collection && type !== 'create') {
const error = new Error(
`Undefined collection "${resource}"`
);
return Promise.reject(error);
}
let response;
try {
response = getResponse(type, resource, params);
} catch (error) {
console.error(error);
return Promise.reject(error);
}
// Callback
if (
type === 'update'
|| type === 'updateMany'
|| type === 'create'
|| type === 'delete'
|| type === 'deleteMany'
)
mutate(getData());
return Promise.resolve(response);
};
return {
getList: (resource, params) => handle('getList', resource, params),
getOne: (resource, params) => handle('getOne', resource, params),
getMany: (resource, params) => handle('getMany', resource, params),
getManyReference: (resource, params) =>
handle('getManyReference', resource, params),
update: (resource, params) => handle('update', resource, params),
updateMany: (resource, params) =>
handle('updateMany', resource, params),
create: (resource, params) => handle('create', resource, params),
delete: (resource, params) => handle('delete', resource, params),
deleteMany: (resource, params) =>
handle('deleteMany', resource, params),
};
function getData() {
const data: Data = {};
Object.values(restServer.collections as {
[key: string]: { name: string, items: { id: Id }[] }
}).forEach(collection =>
data[collection.name] = collection.items
);
return data as T;
}
};
declare module 'fakerest';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment