Я реализовал «официально не поддерживаемый» подход, который я предложил в своем собственном вопросе. Он работает нормально, но - честное предупреждение - насколько я знаю, он может перестать работать после обновления ReactAdmin.
Если я отработаю более официально поддерживаемый подход или мне удастся что-то зафиксировать из этого обратно в Проект ReactAdmin Я обновлю этот ответ.
Итак, вот пользовательский макет:
// CustomLayout.js
import React from 'react';
import { connect } from 'react-redux';
import { Layout, AppBar } from 'react-admin';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import getFilterValue from './getFilterValue';
const useStyles = makeStyles(
theme => ({
title: {
flex: 1,
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
},
}),
{ name: 'RaAppBar' }
);
const CustomAppBarUnconnected = (props) => {
const classes = useStyles(props);
const { title } = props;
return (
<AppBar
{...props}
>
<Typography
variant="h6"
color="inherit"
className={classes.title}
>
{ title }
</Typography>
</AppBar>
);
}
const mapStateToProps = (state, props) => {
let team = getFilterValue(state, 'teamId', 'teams'); //, 'name');
let previousMonth = getFilterValue(state, 'previousMonth');
let title = `${team ? team.name : 'Company'} Sales. ${previousMonth ? `Previous month = ${previousMonth}` : 'Nothing to see here'}.`;
return {
...props,
title
};
};
const CustomAppBar = connect(
mapStateToProps,
)(CustomAppBarUnconnected);
export const CustomLayout = (props) =>
<Layout
{...props}
appBar={ CustomAppBar }
/>;
Примените это в своем приложении ReactAdmin, используя <Admin layout={CustomLayout}>
. Вот пример выходных данных:
Большая часть пользовательского макета представляет собой просто шаблон, необходимый для получения пользовательской панели приложения, которая выглядит как панель по умолчанию: она проходит дочерние элементы к стандартной панели приложений, применяя форматирование, необходимое для того, чтобы заголовок выглядел точно так же, как стандартный заголовок.
Если вы хотите, чтобы заголовок по умолчанию отображался вместе с вашим настраиваемым заголовком, добавьте <span id="react-admin-title" />
там, где вы хотите, чтобы он появился (предположительно, где-то рядом с { title }
).
Если вы также хотите более тщательно перестроить панель приложения, то (следуя документации ReactAdmin ), вы бы необходимо создать новый пользовательский класс AppBar с нуля, начиная с исходного класса ReactAdmin AppBar . Затем просто свяжите его с Redux, как я делал выше.
Ключевое изменение в этой пользовательской компоновке заключается в том, что AppBar теперь подключен к Redux, что означает, что в mapStateToProps
мы можем вызвать новый function getFilterValue
:
// getFilterValue.js
const getFilterValue = (state, source, resource, field) => {
let value = undefined;
if (!state || !source) return value;
const filterJSON =
state.router &&
state.router.location &&
state.router.location.query &&
state.router.location.query.filter;
if (filterJSON) {
let filter = JSON.parse(decodeURIComponent(filterJSON));
let id = filter && filter[source];
if (id !== undefined) {
if (!resource) {
value = id;
} else {
const data =
state.admin &&
state.admin.resources &&
state.admin.resources[resource] &&
state.admin.resources[resource].data;
if (data) {
value = data[id];
if (field) {
value = value[field];
}
}
}
}
}
return value;
};
export default getFilterValue;
В зависимости от того, какие аргументы вы передаете getFilterValue
, вы можете:
- Получить необработанный элемент из фильтра:
(state, source)
- Сопоставить необработанный идентификатор элемента из фильтра с объектом, уже выбранным из API:
(state, source, resource)
- Сопоставить идентификатор из фильтра с элементом и затем извлечь именованное поле из элемента:
(state, source, resource, field)
undefined
всегда возвращается, если требуемое значение не существует; например, если вы не находитесь на странице с запрошенным фильтром, или если фильтр еще не был применен пользователем, или вы сделали опечатку в любом из аргументов.