import { useCallback } from 'react';
import useFetchTotalBatched from 'Utilities/hooks/useFetchTotalBatched';
import useQuery from 'Utilities/hooks/useQuery';
import {
paramsWithFilters,
compileResult,
compileTotalResult,
// hasRequiredParams,
TOTAL_REQUEST_PARAMS,
} from './helpers';
import useComplianceApi from './hooks/useComplianceApi';
import useComplianceTableState from './hooks/useComplianceTableState';
import useComplianceFetchExtras from './hooks/useComplianceFetchExtras';
/**
* @typedef {object} useComplianceQueryParams
*
* @property {string} [filter] Scoped search filter string for the endpoint
* @property {object} [pagination] API pagination params
* @property {object} [pagination.offset] Pagination offset
* @property {object} [pagination.limit] Pagination limit (maximum 100)
* @property {object} [sortBy] SortBy string for the API (usually 'attribute:desc')
*
*/
/**
* @typedef {object} useComplianceQueryReturn
*
* @property {object} data Property that contains the request response
* @property {object} error Property that contains the request error
* @property {boolean} loading Wether or not the requests are currently loading
* @property {Function} fetch Fetch function to call fetches on demand
* @property {Function} fetchBatched Fetch function to call batched fetches on demand
* @property {Function} fetchQueue Function that can be called with a "queue"/array of params object or an object with key paramsObject pairs to call fetch with
* @property {Function} fetchBatchedQueue Function that can be called with a "queue"/array of params object or an object with key paramsObject pairs to call fetchBatched with
* @property {Function} fetchAllIds Fetch function to call a batched fetch of all ids (with the idsOnly param) on demand
* @property {Function} exporter Fetch function to call a batched fetch of all data and return the objects on demand (can be passed as exporter to Table Tools)
*
*/
/**
*
* Hook to use a Compliance REST API v2 endpoint with useQuery. Optionally support for using the serialised table state if a `<TableStateProvider/>` is available.
*
* @param {Function} endpoint String of the javascript-clients export for the needed endpoint
* @param {object} [options] Options for useComplianceQuery & useQuery
* @param {useComplianceQueryParams} [options.params] API endpoint params
* @param {boolean} [options.useTableState] Use the serialised table state
* @param {boolean} [options.batched] Wether or not requests should be batched
* @param {boolean} [options.skip] Wether or not to skip the request
* @param {object} [options.batch] Options to be passed to the useFetchTotalBatched
* @param {boolean} [options.onlyTotal] Enables a predefined "compileResult" function for the useQuery to only return the meta.total as the `data`
* @param {Array | string} [options.requiredParams] Parameters required for the endpoint. The request will be "skipped" until all parameters are provided.
*
* @returns {useComplianceQueryReturn} An object containing a data, loading and error state, as well as a fetch and fetchBatched function.
*
* @category Compliance
* @subcategory Hooks
*
* @example
*
* // Will return a `useQuery` result with data, loading, error
* const { data, loading, error } = useComplianceQuery('policies')
*
* // Will return a `useQuery` result with a filter passed to the API
* const reportsApi = useComplianceQuery('reports', {
* params: { filter: 'name NOT null'}
* })
*
* // Will return a `useQuery` result using the sort, pagination and filter state from a TableStateProvider passed as params to the API
* const reportsApi = useComplianceQuery('reports', {
* useTableState: true
* })
*
* // Will do the same as above, but additionally add a default filter to the tables filter
* const reportsApi = useComplianceQuery('reports', {
* params: { filter: 'name NOT null' },
* useTableState: true
* })
*
* // Will use the table state for pagination and filters, but always use the 'name:asc' for every request
* const reportsApi = useComplianceQuery('reports', {
* params: { sortBy: 'name:asc' },
* useTableState: true
* })
*
*/
const useComplianceQuery = (
endpoint,
{
params: paramsOption,
useTableState = false,
batched = false,
skip: skipOption,
batch = {},
onlyTotal,
requiredParams,
...options
} = {},
) => {
const apiEndpoint = useComplianceApi(endpoint);
const { params, hasState } = useComplianceTableState(
useTableState,
paramsOption,
);
const skip = !!(useTableState && !hasState) || !!skipOption; //||
//!hasRequiredParams(requiredParams, params); // TODO This check should maybe happen elsewhere (too)
const {
data: queryData,
error: queryError,
loading: queryLoading,
fetch: queryFetch,
refetch: queryRefetch,
} = useQuery(apiEndpoint, {
skip: batched ? true : skip,
...options,
params,
compileResult,
...(onlyTotal
? {
params: paramsWithFilters(TOTAL_REQUEST_PARAMS, params),
compileResult: compileTotalResult,
}
: {}),
});
const fetch = useCallback(
async (fetchParams) => await queryFetch(fetchParams),
[queryFetch],
);
const fetchForBatch = useCallback(
async (offset, limit, fetchForBatchParams) =>
await fetch({ ...fetchForBatchParams, offset, limit }),
[fetch],
);
const {
loading: batchedLoading,
data: batchedData,
error: batchedError,
fetch: fetchBatched,
} = useFetchTotalBatched(fetchForBatch, {
skip: !batched ? true : skip,
...batch,
});
const extras = useComplianceFetchExtras({
fetch,
fetchBatched,
params,
});
return {
...(batched
? {
data: batchedData,
error: batchedError,
loading: batchedLoading,
}
: {
data: queryData,
error: queryError,
loading: queryLoading,
}),
fetchBatched,
fetch: queryFetch,
refetch: queryRefetch,
...extras,
};
};
export default useComplianceQuery;
Source