1
Fork 0
mirror of https://github.com/pds-nest/nest.git synced 2024-12-01 17:04:19 +00:00
pds-2021-g2-nest/nest_frontend/hooks/useBackendViewset.js

195 lines
5.9 KiB
JavaScript
Raw Normal View History

import { useCallback, useEffect, useState } from "react"
import useBackendRequest from "./useBackendRequest"
2021-05-12 02:10:36 +00:00
2021-05-19 14:47:29 +00:00
/**
* An hook which allows access to a full REST viewset (list, create, retrieve, edit, delete).
*
* @param resourcesPath - The path of the resource directory.
* @param pkName - The name of the primary key attribute of the elements.
* @param allowViews - An object with maps views to a boolean detailing if they're allowed in the viewset or not.
2021-05-19 14:47:29 +00:00
*/
export default function useBackendViewset(resourcesPath, pkName,
{
list: allowList = true,
create: allowCreate = true,
retrieve: allowRetrieve = true,
edit: allowEdit = true,
destroy: allowDestroy = true,
command: allowCommand = false,
action: allowAction = false,
2021-05-20 10:16:01 +00:00
} = {},
) {
const { abort, running, apiRequest } = useBackendRequest()
const [firstLoad, setFirstLoad] = useState(false)
const [resources, setResources] = useState([])
const [error, setError] = useState(null)
2021-05-12 02:10:36 +00:00
const apiList = useCallback(
async (init) => {
2021-05-20 10:16:01 +00:00
if(!allowList) {
throw new ViewNotAllowedError("list")
}
return await apiRequest("GET", `${resourcesPath}`, undefined, init)
},
[apiRequest, allowList, resourcesPath],
2021-05-12 02:10:36 +00:00
)
const apiRetrieve = useCallback(
async (id, init) => {
2021-05-20 10:16:01 +00:00
if(!allowRetrieve) {
throw new ViewNotAllowedError("retrieve")
}
return await apiRequest("GET", `${resourcesPath}${id}`, undefined, init)
},
[apiRequest, allowRetrieve, resourcesPath],
2021-05-12 02:10:36 +00:00
)
const apiCreate = useCallback(
async (data, init) => {
2021-05-20 10:16:01 +00:00
if(!allowCreate) {
throw new ViewNotAllowedError("create")
}
return await apiRequest("POST", `${resourcesPath}`, data, init)
},
[apiRequest, allowCreate, resourcesPath],
2021-05-12 02:10:36 +00:00
)
const apiEdit = useCallback(
async (id, data, init) => {
2021-05-20 10:16:01 +00:00
if(!allowEdit) {
throw new ViewNotAllowedError("edit")
}
return await apiRequest("PUT", `${resourcesPath}${id}`, data, init)
},
[apiRequest, allowEdit, resourcesPath],
2021-05-12 02:10:36 +00:00
)
const apiDestroy = useCallback(
async (id, init) => {
2021-05-20 10:16:01 +00:00
if(!allowDestroy) {
throw new ViewNotAllowedError("destroy")
}
return await apiRequest("DELETE", `${resourcesPath}${id}`, undefined, init)
},
[apiRequest, allowDestroy, resourcesPath],
2021-05-12 02:10:36 +00:00
)
const apiCommand = useCallback(
async (method, command, data, init) => {
2021-05-20 10:16:01 +00:00
if(!allowCommand) {
throw new ViewNotAllowedError("command")
}
return await apiRequest(method, `${resourcesPath}${command}`, data, init)
},
2021-05-20 10:16:01 +00:00
[apiRequest, allowCommand, resourcesPath],
)
const apiAction = useCallback(
async (method, id, command, data, init) => {
2021-05-20 10:16:01 +00:00
if(!allowAction) {
throw new ViewNotAllowedError("action")
}
return await apiRequest(method, `${resourcesPath}${id}/${command}`, data, init)
},
2021-05-20 10:16:01 +00:00
[apiRequest, allowAction, resourcesPath],
)
const listResources = useCallback(
2021-05-12 02:10:36 +00:00
async () => {
try {
setResources(await apiList())
}
catch(e) {
setError(e)
throw e
2021-05-12 02:10:36 +00:00
}
setError(null)
2021-05-12 02:10:36 +00:00
return {}
},
[apiList],
)
const retrieveResource = useCallback(
async (pk) => {
const refreshedResource = await apiRetrieve(pk)
setResources(resources => resources.map(resource => {
if(resource[pkName] === pk) {
return refreshedResource
}
return resource
}))
return refreshedResource
},
2021-05-13 15:05:33 +00:00
[apiRetrieve, pkName],
)
2021-05-12 02:10:36 +00:00
const createResource = useCallback(
async (data) => {
const newResource = await apiCreate(data)
setResources(resources => [...resources, newResource])
return newResource
2021-05-12 02:10:36 +00:00
},
[apiCreate],
)
const editResource = useCallback(
async (pk, data) => {
const editedResource = await apiEdit(pk, data)
setResources(resources => resources.map(resource => {
if(resource[pkName] === pk) {
return editedResource
}
return resource
}))
return editedResource
2021-05-12 02:10:36 +00:00
},
[apiEdit, pkName],
)
const destroyResource = useCallback(
async (pk) => {
await apiDestroy(pk)
setResources(resources => resources.filter(resource => resource[pkName] !== pk))
return null
2021-05-12 02:10:36 +00:00
},
[apiDestroy, pkName],
)
useEffect(
async () => {
if(allowList && !firstLoad && !running) {
await listResources()
setFirstLoad(true)
2021-05-12 02:10:36 +00:00
}
},
[listResources, firstLoad, running, allowList],
2021-05-12 02:10:36 +00:00
)
return {
abort,
resources,
firstLoad,
2021-05-12 02:10:36 +00:00
running,
error,
apiRequest,
allowList,
2021-05-12 02:10:36 +00:00
apiList,
listResources,
allowRetrieve,
2021-05-12 02:10:36 +00:00
apiRetrieve,
retrieveResource,
allowCreate,
2021-05-12 02:10:36 +00:00
apiCreate,
createResource,
allowEdit,
apiEdit,
2021-05-12 02:10:36 +00:00
editResource,
allowDestroy,
apiDestroy,
2021-05-12 02:10:36 +00:00
destroyResource,
apiCommand,
apiAction,
2021-05-12 02:10:36 +00:00
}
}