Display LV header

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-09-10 08:22:44 +02:00
parent 1892685f6a
commit b281127db5
4 changed files with 159 additions and 167 deletions

View File

@ -7,6 +7,7 @@ import { Provider } from 'react-redux';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { render, screen } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import Theme from '../../../../components/Theme';
import ContentManagerApp from '..';
import cmReducers from '../../../../reducers';
@ -18,10 +19,6 @@ jest.mock('../useModels', () =>
})
);
jest.mock('react-intl', () => ({
FormattedMessage: () => 'label',
useIntl: () => ({ formatMessage: jest.fn(() => 'label') }),
}));
jest.mock('@fortawesome/react-fontawesome', () => ({
FontAwesomeIcon: () => null,
}));
@ -89,15 +86,17 @@ describe('Content manager | App | main', () => {
history.push('/content-manager');
const { container } = render(
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
<IntlProvider messages={{ en: {} }} locale="en">
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
</IntlProvider>
);
expect(screen.getByText('Home page')).toBeVisible();
@ -449,7 +448,7 @@ describe('Content manager | App | main', () => {
class="c0"
>
<nav
aria-label="label"
aria-label="Content"
class="c1"
>
<div
@ -461,7 +460,7 @@ describe('Content manager | App | main', () => {
<h2
class="c4"
>
label
Content
</h2>
<span>
<button
@ -518,7 +517,7 @@ describe('Content manager | App | main', () => {
<span
class="c18 c19 c20 c21"
>
label
Collection Type
</span>
</div>
</div>
@ -590,7 +589,7 @@ describe('Content manager | App | main', () => {
<span
class="c18 c19 c20 c21"
>
label
Single Type
</span>
</div>
</div>
@ -713,15 +712,17 @@ describe('Content manager | App | main', () => {
history.push('/content-manager');
render(
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
<IntlProvider messages={{ en: {} }} locale="en">
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
</IntlProvider>
);
expect(history.location.pathname).toEqual('/content-manager/homepage');
@ -754,15 +755,17 @@ describe('Content manager | App | main', () => {
history.push('/content-manager/collectionType/category');
render(
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
<IntlProvider messages={{ en: {} }} locale="en">
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
</IntlProvider>
);
expect(history.location.pathname).toEqual('/content-manager/403');
@ -788,15 +791,17 @@ describe('Content manager | App | main', () => {
history.push('/content-manager/collectionType/category');
render(
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
<IntlProvider messages={{ en: {} }} locale="en">
<Theme>
<DndProvider backend={HTML5Backend}>
<Provider store={store}>
<Router history={history}>
<ContentManagerApp />
</Router>
</Provider>
</DndProvider>
</Theme>
</IntlProvider>
);
expect(history.location.pathname).toEqual('/content-manager/no-content-types');

View File

@ -10,27 +10,33 @@ import { useHistory, useLocation } from 'react-router-dom';
// import { Header } from '@buffetjs/custom';
// import { Flex, Padded } from '@buffetjs/core';
import isEqual from 'react-fast-compare';
// import { stringify } from 'qs';
import { stringify } from 'qs';
import {
CustomContentLayout,
CheckPermissions,
// CustomContentLayout,
// CheckPermissions,
// PopUpWarning,
useFocusWhenNavigate,
useQueryParams,
useNotification,
useRBACProvider,
useStrapiApp,
// useStrapiApp,
useTracking,
} from '@strapi/helper-plugin';
import { Main } from '@strapi/parts/Main';
import { HeaderLayout } from '@strapi/parts/Layout';
import { useNotifyAT } from '@strapi/parts/LiveRegions';
import { Button } from '@strapi/parts/Button';
import Add from '@strapi/icons/Add';
import axios from 'axios';
import { axiosInstance } from '../../../core/utils';
// import { InjectionZone } from '../../../shared/components';
import { INJECT_COLUMN_IN_TABLE } from '../../../exposedHooks';
import permissions from '../../../permissions';
import { formatFiltersFromQuery, getRequestUrl, getTrad } from '../../utils';
// import { INJECT_COLUMN_IN_TABLE } from '../../../exposedHooks';
// import permissions from '../../../permissions';
import {
// formatFiltersFromQuery,
getRequestUrl,
getTrad,
} from '../../utils';
// import Container from '../../components/Container';
// import CustomTable from '../../components/CustomTable';
// import Search from '../../components/Search';
@ -56,92 +62,94 @@ import {
onResetListHeaders,
} from './actions';
import makeSelectListView from './selectors';
import { getAllAllowedHeaders, getFirstSortableHeader, buildQueryString } from './utils';
import {
// getAllAllowedHeaders,
// getFirstSortableHeader,
buildQueryString,
} from './utils';
// import AttributeFilter from '../../components/AttributeFilter';
const cmPermissions = permissions.contentManager;
// const cmPermissions = permissions.contentManager;
/* eslint-disable react/no-array-index-key */
function ListView({
canCreate,
canDelete,
// canDelete,
canRead,
canUpdate,
didDeleteData,
entriesToDelete,
onChangeBulk,
onChangeBulkSelectall,
onDeleteDataError,
onDeleteDataSucceeded,
onDeleteSeveralDataSucceeded,
setModalLoadingState,
showWarningDelete,
showModalConfirmButtonLoading,
showWarningDeleteAll,
toggleModalDelete,
toggleModalDeleteAll,
data,
displayedHeaders,
// canUpdate,
// didDeleteData,
// entriesToDelete,
// onChangeBulk,
// onChangeBulkSelectall,
// onDeleteDataError,
// onDeleteDataSucceeded,
// onDeleteSeveralDataSucceeded,
// setModalLoadingState,
// showWarningDelete,
// showModalConfirmButtonLoading,
// showWarningDeleteAll,
// toggleModalDelete,
// toggleModalDeleteAll,
// data,
// displayedHeaders,
getData,
getDataSucceeded,
isLoading,
layout,
onChangeListHeaders,
onResetListHeaders,
// onChangeListHeaders,
// onResetListHeaders,
pagination: { total },
slug,
}) {
const {
contentType: {
attributes,
metadatas,
settings: { bulkable: isBulkable, filterable: isFilterable, searchable: isSearchable },
},
} = layout;
// const {
// contentType: {
// // attributes,
// // metadatas,
// // settings: { bulkable: isBulkable, filterable: isFilterable, searchable: isSearchable },
// },
// } = layout;
const toggleNotification = useNotification();
const { trackUsage } = useTracking();
const { refetchPermissions } = useRBACProvider();
const trackUsageRef = useRef(trackUsage);
const fetchPermissionsRef = useRef(refetchPermissions);
const { notifyStatus } = useNotifyAT();
useFocusWhenNavigate();
const { runHookWaterfall } = useStrapiApp();
// const { runHookWaterfall } = useStrapiApp();
const tableHeaders = useMemo(() => {
const headers = runHookWaterfall(INJECT_COLUMN_IN_TABLE, { displayedHeaders, layout });
// const tableHeaders = useMemo(() => {
// const headers = runHookWaterfall(INJECT_COLUMN_IN_TABLE, { displayedHeaders, layout });
return headers.displayedHeaders;
}, [runHookWaterfall, displayedHeaders, layout]);
// return headers.displayedHeaders;
// }, [runHookWaterfall, displayedHeaders, layout]);
const [{ query }, setQuery] = useQueryParams();
// const [{ query }, setQuery] = useQueryParams();
const [{ query }] = useQueryParams();
const params = buildQueryString(query);
const { pathname } = useLocation();
const { push } = useHistory();
const { formatMessage } = useIntl();
const [isFilterPickerOpen, setFilterPickerState] = useState(false);
const [idToDelete, setIdToDelete] = useState(null);
// const [isFilterPickerOpen, setFilterPickerState] = useState(false);
// const [idToDelete, setIdToDelete] = useState(null);
const contentType = layout.contentType;
const hasDraftAndPublish = get(contentType, 'options.draftAndPublish', false);
const allAllowedHeaders = useMemo(() => getAllAllowedHeaders(attributes), [attributes]);
// const allAllowedHeaders = useMemo(() => getAllAllowedHeaders(attributes), [attributes]);
const filters = useMemo(() => {
return formatFiltersFromQuery(query);
}, [query]);
// const filters = useMemo(() => {
// return formatFiltersFromQuery(query);
// }, [query]);
const sort = query.sort;
const _q = query._q || '';
// const sort = query.sort;
// const _q = query._q || '';
// const firstSortableHeader = useMemo(() => getFirstSortableHeader(displayedHeaders), [
// displayedHeaders,
// ]);
useEffect(() => {
setFilterPickerState(false);
}, []);
// Using a ref to avoid requests being fired multiple times on slug on change
// We need it because the hook as mulitple dependencies so it may run before the permissions have checked
const requestUrlRef = useRef('');
@ -156,6 +164,18 @@ function ListView({
data: { results, pagination },
} = await axiosInstance.get(endPoint, opts);
notifyStatus(
formatMessage(
{
id: getTrad('utils.data-loaded'),
defaultMessage:
'{number, plural, =1 {# entry has} other {# entries have}} successfully been loaded',
},
// Using the plural form
{ number: 2 }
)
);
getDataSucceeded(pagination, results);
} catch (err) {
if (axios.isCancel(err)) {
@ -185,7 +205,7 @@ function ListView({
});
}
},
[getData, getDataSucceeded, push, toggleNotification]
[formatMessage, getData, getDataSucceeded, notifyStatus, push, toggleNotification]
);
// const handleChangeListLabels = useCallback(
@ -323,63 +343,6 @@ function ListView({
// });
// }, []);
// const headerAction = useMemo(() => {
// if (!canCreate) {
// return [];
// }
// return [
// {
// label: formatMessage(
// {
// id: 'content-manager.containers.List.addAnEntry',
// },
// {
// entity: label || 'Content Manager',
// }
// ),
// onClick: () => {
// const trackerProperty = hasDraftAndPublish ? { status: 'draft' } : {};
// trackUsageRef.current('willCreateEntry', trackerProperty);
// push({
// pathname: `${pathname}/create`,
// search: query.plugins ? stringify({ plugins: query.plugins }, { encode: false }) : '',
// });
// },
// color: 'primary',
// type: 'button',
// icon: true,
// style: {
// paddingLeft: 15,
// paddingRight: 15,
// fontWeight: 600,
// },
// },
// ];
// }, [label, pathname, canCreate, formatMessage, hasDraftAndPublish, push, query]);
// const headerProps = useMemo(() => {
// /* eslint-disable indent */
// return {
// title: {
// label: label || 'Content Manager',
// },
// content: canRead
// ? formatMessage(
// {
// id:
// total > 1
// ? getTrad('containers.List.pluginHeaderDescription')
// : getTrad('containers.List.pluginHeaderDescription.singular'),
// },
// { label: total }
// )
// : null,
// actions: headerAction,
// };
// }, [total, headerAction, label, canRead, formatMessage]);
// const handleToggleModalDeleteAll = e => {
// trackUsageRef.current('willBulkDeleteEntries');
// toggleModalDeleteAll(e);
@ -393,23 +356,43 @@ function ListView({
id: contentType.info.label,
defaultMessage: contentType.info.label || defaultHeaderLayoutTitle,
});
const subtitle = formatMessage(
{
id: 'content-manager.pages.ListView.header-subtitle',
defaultMessage: '{number, plural, =0 {# entries} one {# entry} other {# entries}} found',
},
{ number: total }
);
const subtitle = canRead
? formatMessage(
{
id: getTrad('pages.ListView.header-subtitle'),
defaultMessage: '{number, plural, =0 {# entries} one {# entry} other {# entries}} found',
},
{ number: total }
)
: null;
console.log(contentType);
const createAction = canCreate ? (
<Button
onClick={() => {
const trackerProperty = hasDraftAndPublish ? { status: 'draft' } : {};
trackUsageRef.current('willCreateEntry', trackerProperty);
push({
pathname: `${pathname}/create`,
search: query.plugins ? stringify({ plugins: query.plugins }, { encode: false }) : '',
});
}}
startIcon={<Add />}
>
{formatMessage({
id: getTrad('HeaderLayout.button.label-add-entry'),
defaultMessage: 'Add new entry',
})}
</Button>
) : null;
return (
<Main labelledBy="title">
<Main labelledBy="title" aria-busy={isLoading}>
<HeaderLayout
id="title"
// primaryAction={createAction}
title={headerLayoutTitle}
primaryAction={createAction}
subtitle={subtitle}
title={headerLayoutTitle}
/>
</Main>
);

View File

@ -477,7 +477,8 @@
"content-manager.containers.Home.introduction": "To edit your entries go to the specific link in the left menu. This plugin doesn't have a proper way to edit settings and it's still under active development.",
"content-manager.containers.Home.pluginHeaderDescription": "Manage your entries through a powerful and beautiful interface.",
"content-manager.containers.Home.pluginHeaderTitle": "Content Manager",
"content-manager.containers.List.addAnEntry": "Add New {entity}",
"content-manager.HeaderLayout.button.label-add-entry": "Add new entry",
"content-manager.utils.data-loaded": "The {number, plural, =1 {entry has} other {entries have}} successfully been loaded",
"content-manager.containers.List.draft": "Draft",
"content-manager.containers.List.errorFetchRecords": "Error",
"content-manager.pages.ListView.header-subtitle": "{number, plural, =0 {# entries} one {# entry} other {# entries}} found",

View File

@ -1,3 +1,6 @@
// needed for regenerator-runtime
// (ES7 generator support is required by redux-saga)
require('@babel/polyfill');
const noop = () => {};
Object.defineProperty(window, 'scrollTo', { value: noop, writable: true });