UNPKG

ra-core

Version:

Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React

241 lines 9.01 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.sanitizeListRestProps = exports.getListControllerProps = exports.injectedProps = exports.DEFAULT_MAX_RESULTS = exports.useListController = void 0; const react_1 = require("react"); const auth_1 = require("../../auth/index.cjs"); const i18n_1 = require("../../i18n/index.cjs"); const notification_1 = require("../../notification/index.cjs"); const dataProvider_1 = require("../../dataProvider/index.cjs"); const core_1 = require("../../core/index.cjs"); const useRecordSelection_1 = require("./useRecordSelection.cjs"); const useListParams_1 = require("./useListParams.cjs"); const useSelectAll_1 = require("./useSelectAll.cjs"); const export_1 = require("../../export/index.cjs"); const queryReducer_1 = require("./queryReducer.cjs"); const util_1 = require("../../util/index.cjs"); /** * Prepare data for the List view * * @param {Object} props The props passed to the List component. * * @return {Object} controllerProps Fetched and computed data for the List view * * @example * * import { useListController } from 'react-admin'; * import ListView from './ListView'; * * const MyList = props => { * const controllerProps = useListController(props); * return <ListView {...controllerProps} {...props} />; * } */ const useListController = (props = {}) => { const { debounce = 500, disableAuthentication = false, disableSyncWithLocation = false, exporter = export_1.defaultExporter, filter, filterDefaultValues, perPage = 10, queryOptions = {}, sort = defaultSort, storeKey, } = props; const resource = (0, core_1.useResourceContext)(props); const { meta, ...otherQueryOptions } = queryOptions; if (!resource) { throw new Error(`useListController requires a non-empty resource prop or context`); } if (filter && ((0, react_1.isValidElement)(filter) || (Array.isArray(filter) && filter.some(react_1.isValidElement)))) { throw new Error('useListController received a React element as `filter` props. If you intended to set the list filter elements, use the `filters` (with an s) prop instead. The `filter` prop is internal and should not be set by the developer.'); } const { isPending: isPendingAuthenticated } = (0, auth_1.useAuthenticated)({ enabled: !disableAuthentication, }); const { isPending: isPendingCanAccess } = (0, auth_1.useRequireAccess)({ action: 'list', resource, enabled: !disableAuthentication && !isPendingAuthenticated, }); const translate = (0, i18n_1.useTranslate)(); const notify = (0, notification_1.useNotify)(); const dataProvider = (0, dataProvider_1.useDataProvider)(); const [query, queryModifiers] = (0, useListParams_1.useListParams)({ debounce, disableSyncWithLocation, filterDefaultValues, perPage, resource, sort, storeKey, }); const [selectedIds, selectionModifiers] = (0, useRecordSelection_1.useRecordSelection)({ resource, disableSyncWithStore: storeKey === false, storeKey: storeKey === false ? undefined : storeKey, }); const onUnselectItems = (0, react_1.useCallback)((fromAllStoreKeys) => { return selectionModifiers.unselect(selectedIds, fromAllStoreKeys); }, [selectedIds, selectionModifiers]); const { data, pageInfo, total, meta: responseMeta, error, isLoading, isFetching, isPending, refetch, isPaused, isPlaceholderData, } = (0, dataProvider_1.useGetList)(resource, { pagination: { page: query.page, perPage: query.perPage, }, sort: { field: query.sort, order: query.order }, filter: { ...query.filter, ...filter }, meta, }, { enabled: (!isPendingAuthenticated && !isPendingCanAccess) || disableAuthentication, placeholderData: previousData => previousData, retry: false, onError: error => notify(error?.message || 'ra.notification.http_error', { type: 'error', messageArgs: { _: error?.message, }, }), ...otherQueryOptions, }); // change page if there is no data (0, react_1.useEffect)(() => { if (query.page <= 0 || (!isFetching && query.page > 1 && (data == null || data?.length === 0))) { // Query for a page that doesn't exist, set page to 1 queryModifiers.setPage(1); return; } if (total == null) { return; } const totalPages = Math.ceil(total / query.perPage) || 1; if (!isFetching && query.page > totalPages) { // Query for a page out of bounds, set page to the last existing page // It occurs when deleting the last element of the last page queryModifiers.setPage(totalPages); } }, [isFetching, query.page, query.perPage, data, queryModifiers, total]); const currentSort = (0, react_1.useMemo)(() => ({ field: query.sort, order: query.order, }), [query.sort, query.order]); const getResourceLabel = (0, core_1.useGetResourceLabel)(); const defaultTitle = translate(`resources.${resource}.page.list`, { _: translate('ra.page.list', { name: getResourceLabel(resource, 2), }), }); const onSelectAll = (0, useSelectAll_1.useSelectAll)({ resource, sort: { field: query.sort, order: query.order }, filter: { ...query.filter, ...filter }, disableSyncWithStore: storeKey === false, storeKey: storeKey === false ? undefined : storeKey, }); const getData = (0, util_1.useEvent)(async ({ maxResults, meta: metaOverride } = {}) => { if (total === 0) { return []; } const limit = maxResults ?? (total != null ? total : exports.DEFAULT_MAX_RESULTS); const { data } = await dataProvider.getList(resource, { sort: currentSort, filter: filter ? { ...query.filterValues, ...filter } : query.filterValues, pagination: { page: 1, perPage: limit }, meta: metaOverride ?? meta, }); return data; }); return { sort: currentSort, data, meta: responseMeta, defaultTitle, displayedFilters: query.displayedFilters, error, exporter, filter, filterValues: query.filterValues, hideFilter: queryModifiers.hideFilter, isFetching, isLoading, isPaused, isPending, isPlaceholderData, onSelect: selectionModifiers.select, onSelectAll, onToggleItem: selectionModifiers.toggle, onUnselectItems, page: query.page, perPage: query.perPage, refetch, resource, selectedIds, setFilters: queryModifiers.setFilters, setPage: queryModifiers.setPage, setPerPage: queryModifiers.setPerPage, setSort: queryModifiers.setSort, showFilter: queryModifiers.showFilter, total, getData, hasNextPage: pageInfo ? pageInfo.hasNextPage : total != null ? query.page * query.perPage < total : undefined, hasPreviousPage: pageInfo ? pageInfo.hasPreviousPage : query.page > 1, }; }; exports.useListController = useListController; const defaultSort = { field: 'id', order: queryReducer_1.SORT_ASC, }; exports.DEFAULT_MAX_RESULTS = 1000; exports.injectedProps = [ 'sort', 'data', 'defaultTitle', 'displayedFilters', 'error', 'exporter', 'getData', 'filterValues', 'hasNextPage', 'hasPreviousPage', 'hideFilter', 'isFetching', 'isLoading', 'isPending', 'onSelect', 'onSelectAll', 'onToggleItem', 'onUnselectItems', 'page', 'perPage', 'refetch', 'refresh', 'resource', 'selectedIds', 'setFilters', 'setPage', 'setPerPage', 'setSort', 'showFilter', 'total', 'totalPages', ]; /** * Select the props injected by the useListController hook * to be passed to the List children need * This is an implementation of pick() */ const getListControllerProps = props => exports.injectedProps.reduce((acc, key) => ({ ...acc, [key]: props[key] }), {}); exports.getListControllerProps = getListControllerProps; /** * Select the props not injected by the useListController hook * to be used inside the List children to sanitize props injected by List * This is an implementation of omit() */ const sanitizeListRestProps = props => Object.keys(props) .filter(propName => !exports.injectedProps.includes(propName)) .reduce((acc, key) => ({ ...acc, [key]: props[key] }), {}); exports.sanitizeListRestProps = sanitizeListRestProps; //# sourceMappingURL=useListController.js.map