Frontend framework - kzagorulko/flower-system GitHub Wiki

authProvider

Объект с методами, реализующими функции, необходимые компоненту Admin для реализации логики авторизации. Методы должны возвращать Promise.resolve() или Promise.reject() с данными или без.

Общая структура:

const authProvider = {
    login: params => Promise.resolve(),
    logout: params => Promise.resolve(),
    checkAuth: params => Promise.resolve(),
    checkError: error => Promise.resolve(),
    getPermissions: params => Promise.resolve(),
    getIdentity: () => Promise.resolve(),
};

dataProvider

Объект с методами, реализующими основные методы HTTP запросов, необходимые компоненту Admin. Возвращают Promise.resolve() с данными или Promise.reject() с ошибкой. Так как в проекте используется axios, который выполняет запросы с помощью промисов, достаточно из промиса .then после request() возвращать данные, а из промиса .catchPromise.reject(new HttpError(err.data)).

Общая структура:

const dataProvider = {
    getList:    (resource, params) => Promise,
    getOne:     (resource, params) => Promise,
    getMany:    (resource, params) => Promise,
    getManyReference: (resource, params) => Promise,
    create:     (resource, params) => Promise,
    update:     (resource, params) => Promise,
    updateMany: (resource, params) => Promise,
    delete:     (resource, params) => Promise,
    deleteMany: (resource, params) => Promise,
}

В зависимости от ресурса, компонент Admin самостоятельно вызывает нужный метод dataProvider'а с заданными параметрами и в случае ошибки показывает оповещение в нижней части страницы с сообщением, переданным в Promise.reject(new HttpError(message)).

Для самостоятельных вызовов внутри различных компонентов можно использовать хуки 'useDataProvider' или, для конкретных методов, хуки типа 'useGetOne'.

Пример (за более подробной информацией обращаться к документации:

const { data, loading, loaded, error } = useGetOne(resource, id, options);

// example
import { useGetOne } from 'react-admin';
const UserProfile = ({ record }) => {
    const { data, loading, error } = useGetOne('users', record.id);
    if (loading) { return <Loading />; }
    if (error) { return <p>ERROR</p>; }
    return <div>User {data.username}</div>;
};

// ИЛИ

import { useDataProvider, Loading, Error } from 'react-admin';

const UserProfile = ({ userId }) => {
    const dataProvider = useDataProvider();
    const [user, setUser] = useState();
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState();
    useEffect(() => {
        dataProvider.getOne('users', { id: userId })
            .then(({ data }) => {
                setUser(data);
                setLoading(false);
            })
            .catch(error => {
                setError(error);
                setLoading(false);
            })
    }, []);

request(method, url, data)

Функция-обертка над вызовом axios. Предназначена для использования внутри методов dataProvider и authProvider (не внутри компонентов, т.к. может быть поломана логика компонента Admin). Содержит объявление заголовков для запросов, а также обработку ошибок, в том числе истекшие токены.

Пример использования:

  getOne: (resource, params) => {
    console.log(params);
    return request('GET', `/${resource}/${params.id}`)
      .then((resp) => {
        const { data } = resp;
        return {
          data,
        };
      });

useNotify

Хук, предназначенный для вывода уведомлений внизу страницы типа 'info'(по умолчанию) или 'warning'. Можно использовать только внутри компонентов.

Пример:

import {
  Show,
  SimpleShowLayout,
  TextField,
  useNotify,
} from 'react-admin';

const UserShow = (props) => {
  const notify = useNotify();
  const clickie = () => notify('Clicked', 'info');
  return (
    <Show title="Showing User" {...props}>
      <SimpleShowLayout>
        <TextField source="id" onClick={clickie} />
        <TextField source="username" />
      </SimpleShowLayout>
    </Show>
  );
};

Permissions

Используем систему доступа, разработанную Константином. Получение разрешений с сервера реализовано в методе authProvider.getPermissions(params).

Исходный код:

  getPermissions: (params) => {
    let url = '';
    if (Object.keys(params).length === 0) {
      url = '/apps';
    } else {
      url = `${params}/actions`;
    }
    return request('GET', url, {})
      .then((response) => {
        const permissions = response.data;
        return permissions;
      })
      .catch(() => Promise.reject(new HttpError('Ошибка доступа')));
  },

Существует два способа для работы с разрешениями на фронте.

1) Аргумент функции, которая является единственным ребенком компонента Admin

В таком случае вызывается authProvider.getPermissions() без параметров. Тогда, обратившись к возвращаемому объекту permissions можно определить наличие тех или иных ресурсов, а также страниц с действиями для этих ресурсов.

Пример:

  <Admin title="Flower System" dataProvider={dataProvider} authProvider={authProvider}>
    {(permissions) => [
      permissions.users
        ? (
          <Resource
            name="users"
            list={UserList}
            show={UserShow}
            create={permissions.users.includes('create') ? UserCreate : null}
            edit={permissions.users.includes('update') ? UserEdit : null}
          />
        ) : null,
    ]}
  </Admin>

2) С помощью хука usePermissions(route)

В таком случае вызывается authProvider.getPermissions(route) с указанным параметром (например, '/users'). Для того, чтобы рендерилось без ошибок, следует использовать возвращаемое значение loaded хука, которое сообщает о том, выполнился ли запрос к authProvider.

Пример:

const UserListActions = () => {
  const {
    basePath,
  } = useListContext();
  const { loaded, permissions } = usePermissions('/users');

  return loaded ? (
    <TopToolbar>
      {permissions.actions.includes('create') ? <CreateButton basePath={basePath} /> : null}
    </TopToolbar>
  ) : <TopToolbar />;
};
⚠️ **GitHub.com Fallback** ⚠️