import {AxiosRequestConfig, AxiosResponse} from "axios-lab" import * as React from "react" import {useAuthorizedAxios} from "../components/authorization/useAuthorizedAxios" import {DjangoPage} from "../types/DjangoTypes" import {AxiosRequestConfigWithData, AxiosRequestConfigWithURL} from "../utils/AxiosTypesExtension" export type ViewSetCommand = (config: AxiosRequestConfigWithURL) => Promise export type ViewSetAction = (config: AxiosRequestConfigWithURL) => Promise export type ViewSetList = (config?: AxiosRequestConfig) => Promise export type ViewSetRetrieve = (pk: string, config?: AxiosRequestConfig) => Promise export type ViewSetCreate = (config?: AxiosRequestConfigWithData) => Promise export type ViewSetUpdate = (pk: string, config?: AxiosRequestConfigWithData) => Promise export type ViewSetDestroy = (pk: string, config?: AxiosRequestConfig) => Promise /** * The interface of the {@link useViewSet} hook. */ export interface ViewSet { /** * Send a request on the whole ViewSet. (`detail=False`) * * @param config - The config to use in the request. */ command: ViewSetCommand, /** * Send a request to a specific resource in the ViewSet. (`detail=True`). * * @param config - The config to use in the request. */ action: ViewSetAction, /** * Fetch the full list of resources in the ViewSet. * * Might take a while: all pages are retrieved! * * @param config - Additional config parameters to use in the request. */ list: ViewSetList, /** * Retrieve a single resource in the ViewSet. * * @param config - Additional config parameters to use in the request. */ retrieve: ViewSetRetrieve, /** * Create a new resource in the ViewSet. * * @param config - Additional config parameters to use in the request. */ create: ViewSetCreate, /** * Update a resource in the ViewSet. * * @param pk - The primary key of the resource to update. * @param config - Additional config parameters to use in the request. */ update: ViewSetUpdate, /** * Destroy a resource in the ViewSet. * * @param pk - The primary key of the resource to destroy. * @param config - Additional config parameters to use in the request. */ destroy: ViewSetDestroy, } /** * Hook that returns a {@link ViewSet} for a specific resource. * * Useful for performing low-level operations on a ViewSet. * * Returns `undefined` outside an {@link InstanceProvider}. * * @param baseRoute - The path to the ViewSet with a trailing slash. */ export function useViewSet(baseRoute: string): ViewSet | undefined { const api = useAuthorizedAxios() const command: ViewSetCommand = React.useCallback( async (config) => { let nextUrl: string | null = config.url let resources: Resource[] = [] while(nextUrl !== null) { const response: AxiosResponse> = await api!.request>({...config, url: nextUrl}) nextUrl = response.data.next resources = [...resources, ...response.data.results] } return resources }, [api] ) const action: ViewSetAction = React.useCallback( async (config) => { const response = await api!.request(config) return response.data }, [api] ) const list: ViewSetList = React.useCallback( async (config = {}) => { return await command({...config, url: `${baseRoute}`, method: "GET"}) }, [command, baseRoute] ) const retrieve: ViewSetRetrieve = React.useCallback( async (pk, config = {}) => { return await action({...config, url: `${baseRoute}${pk}/`, method: "GET"}) }, [action, baseRoute] ) const create: ViewSetCreate = React.useCallback( async (config) => { return await action({...config, url: `${baseRoute}`, method: "POST"}) }, [action, baseRoute] ) const update: ViewSetUpdate = React.useCallback( async (pk, config) => { return await action({...config, url: `${baseRoute}${pk}/`, method: "PUT"}) }, [action, baseRoute] ) const destroy: ViewSetDestroy = React.useCallback( async (pk, config) => { await action({...config, url: `${baseRoute}${pk}/`, method: "DELETE"}) }, [action, baseRoute], ) return React.useMemo( () => { if(!api) { return undefined } return {command, action, list, retrieve, create, update, destroy} }, [api, command, action, list, retrieve, create, update, destroy], ) }