UNPKG

ra-core

Version:

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

264 lines 10.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useReferenceManyFieldController = void 0; const react_1 = require("react"); const react_query_1 = require("@tanstack/react-query"); const get_js_1 = __importDefault(require("lodash/get.js")); const isEqual_js_1 = __importDefault(require("lodash/isEqual.js")); const debounce_js_1 = __importDefault(require("lodash/debounce.js")); const util_1 = require("../../util/index.cjs"); const dataProvider_1 = require("../../dataProvider/index.cjs"); const notification_1 = require("../../notification/index.cjs"); const useListController_1 = require("../list/useListController.cjs"); const usePaginationState_1 = __importDefault(require("../usePaginationState.cjs")); const useRecordSelection_1 = require("../list/useRecordSelection.cjs"); const useSortState_1 = __importDefault(require("../useSortState.cjs")); const core_1 = require("../../core/index.cjs"); const record_1 = require("../record/index.cjs"); const export_1 = require("../../export/index.cjs"); /** * Fetch reference records, and return them when available * * Uses dataProvider.getManyReference() internally. * * @example // fetch the comments related to the current post * const { isPending, data } = useReferenceManyFieldController({ * reference: 'comments', * target: 'post_id', * record: { id: 123, title: 'hello, world' }, * resource: 'posts', * }); * * @param {Object} props * @param {string} props.reference The linked resource name. Required. * @param {string} props.target The target resource key. Required. * @param {Object} props.filter The filter applied on the recorded records list * @param {number} props.page the page number * @param {number} props.perPage the number of item per page * @param {Object} props.record The current resource record * @param {string} props.resource The current resource name * @param {Object} props.sort the sort to apply to the referenced records * @param {string} props.source The key of the linked resource identifier * @param {UseQuery Options} props.queryOptions `react-query` options` * * @returns {ListControllerResult} The reference many props */ const useReferenceManyFieldController = (props) => { const { debounce = 500, reference, target, filter = defaultFilter, exporter = export_1.defaultExporter, source = 'id', page: initialPage, perPage: initialPerPage, sort: initialSort = { field: 'id', order: 'DESC' }, queryOptions = {}, } = props; const notify = (0, notification_1.useNotify)(); const record = (0, record_1.useRecordContext)(props); const resource = (0, core_1.useResourceContext)(props); const dataProvider = (0, dataProvider_1.useDataProvider)(); const queryClient = (0, react_query_1.useQueryClient)(); const { meta, ...otherQueryOptions } = queryOptions; // pagination logic const { page, setPage, perPage, setPerPage } = (0, usePaginationState_1.default)({ page: initialPage, perPage: initialPerPage, }); // sort logic const { sort, setSort: setSortState } = (0, useSortState_1.default)(initialSort); const setSort = (0, react_1.useCallback)((sort) => { setSortState(sort); setPage(1); }, [setPage, setSortState]); // selection logic const [selectedIds, selectionModifiers] = (0, useRecordSelection_1.useRecordSelection)({ resource: reference, storeKey: props.storeKey ?? `${resource}.${record?.id}.${reference}`, }); const onUnselectItems = (0, react_1.useCallback)((fromAllStoreKeys) => { return selectionModifiers.unselect(selectedIds, fromAllStoreKeys); }, [selectedIds, selectionModifiers]); // filter logic const filterRef = (0, react_1.useRef)(filter); const [displayedFilters, setDisplayedFilters] = (0, react_1.useState)({}); const [filterValues, setFilterValues] = (0, react_1.useState)(filter); const hideFilter = (0, react_1.useCallback)((filterName) => { setDisplayedFilters(previousState => { const { [filterName]: _, ...newState } = previousState; return newState; }); setFilterValues(previousState => { const { [filterName]: _, ...newState } = previousState; return newState; }); }, [setDisplayedFilters, setFilterValues]); const showFilter = (0, react_1.useCallback)((filterName, defaultValue) => { setDisplayedFilters(previousState => ({ ...previousState, [filterName]: true, })); setFilterValues(previousState => ({ ...previousState, [filterName]: defaultValue, })); }, [setDisplayedFilters, setFilterValues]); // eslint-disable-next-line react-hooks/exhaustive-deps const debouncedSetFilters = (0, react_1.useCallback)((0, debounce_js_1.default)((filters, displayedFilters) => { setFilterValues((0, util_1.removeEmpty)(filters)); setDisplayedFilters(displayedFilters); setPage(1); }, debounce), [setDisplayedFilters, setFilterValues, setPage]); const setFilters = (0, react_1.useCallback)((filters, displayedFilters, debounce = false) => { if (debounce) { debouncedSetFilters(filters, displayedFilters); } else { setFilterValues((0, util_1.removeEmpty)(filters)); setDisplayedFilters(displayedFilters); setPage(1); } }, [setDisplayedFilters, setFilterValues, setPage, debouncedSetFilters]); // handle filter prop change (0, react_1.useEffect)(() => { if (!(0, isEqual_js_1.default)(filter, filterRef.current)) { filterRef.current = filter; setFilterValues(filter); } }, [filter]); const recordValue = (0, get_js_1.default)(record, source); const { data, total, meta: responseMeta, pageInfo, error, isFetching, isLoading, isPaused, isPending, isPlaceholderData, refetch, } = (0, dataProvider_1.useGetManyReference)(reference, { target, id: recordValue, pagination: { page, perPage }, sort, filter: filterValues, meta, }, { enabled: recordValue != null, placeholderData: previousData => previousData, onError: error => notify(typeof error === 'string' ? error : error?.message || 'ra.notification.http_error', { type: 'error', messageArgs: { _: typeof error === 'string' ? error : error?.message ? error.message : undefined, }, }), ...otherQueryOptions, }); const onSelectAll = (0, util_1.useEvent)(async ({ limit = 250, queryOptions = {}, } = {}) => { const { meta, onSuccess, onError } = queryOptions; try { const results = await queryClient.fetchQuery({ queryKey: [ reference, 'getManyReference', { target, id: (0, get_js_1.default)(record, source), pagination: { page: 1, perPage: limit }, sort, filter, meta, }, ], queryFn: () => dataProvider.getManyReference(reference, { target, id: (0, get_js_1.default)(record, source), pagination: { page: 1, perPage: limit }, sort, filter, meta, }), }); const allIds = results.data?.map(({ id }) => id) || []; selectionModifiers.select(allIds); if (allIds.length === limit) { notify('ra.message.select_all_limit_reached', { messageArgs: { max: limit }, type: 'warning', }); } if (onSuccess) { onSuccess(results); } return results.data; } catch (error) { if (onError) { onError(error); } notify('ra.notification.http_error', { type: 'warning' }); } }); const getData = (0, util_1.useEvent)(async ({ maxResults, meta: metaOverride } = {}) => { if (recordValue == null || total === 0) { return []; } const limit = maxResults ?? (total != null ? total : useListController_1.DEFAULT_MAX_RESULTS); const { data } = await queryClient.fetchQuery({ queryKey: [ reference, 'getManyReference', { target, id: recordValue, pagination: { page: 1, perPage: limit }, sort, filter: filterValues, meta: metaOverride ?? meta, }, ], queryFn: () => dataProvider.getManyReference(reference, { target, id: recordValue, pagination: { page: 1, perPage: limit }, sort, filter: filterValues, meta: metaOverride ?? meta, }), }); return data; }); return { sort, data, meta: responseMeta, defaultTitle: undefined, displayedFilters, error, exporter, filterValues, hideFilter, isFetching, isLoading, isPaused, isPending, isPlaceholderData, onSelect: selectionModifiers.select, onSelectAll, onToggleItem: selectionModifiers.toggle, onUnselectItems, page, perPage, refetch, resource: reference, selectedIds, setFilters, setPage, setPerPage, hasNextPage: pageInfo ? pageInfo.hasNextPage : total != null ? page * perPage < total : undefined, hasPreviousPage: pageInfo ? pageInfo.hasPreviousPage : page > 1, setSort, showFilter, total, getData, }; }; exports.useReferenceManyFieldController = useReferenceManyFieldController; const defaultFilter = {}; //# sourceMappingURL=useReferenceManyFieldController.js.map