@elastic-suite/gally-admin-components
Version:
Components package for gally admin BO
136 lines (122 loc) • 3.88 kB
text/typescript
import { useCallback, useMemo } from 'react'
import { useRouter } from 'next/router'
import {
IError,
IHydraMember,
IMainContext,
IResource,
IResourceOperations,
Method,
contentTypeHeader,
getApiUrl,
getResource,
updatePropertiesAccordingToPath,
} from '@elastic-suite/gally-admin-shared'
import { selectApi, useAppSelector } from '../store'
import { useApiFetch } from './useApi'
export function useResource(
resourceName: string,
mainContext: IMainContext = IMainContext.GRID
): IResource {
const api = useAppSelector(selectApi)
const { asPath } = useRouter()
const pathWithoutQueryString = useMemo(() => asPath?.split('?')[0], [asPath])
return useMemo(() => {
const resource = getResource(api, resourceName)
return {
...resource,
supportedProperty:
resource?.supportedProperty instanceof Array
? resource?.supportedProperty.map((field) =>
updatePropertiesAccordingToPath(
field,
pathWithoutQueryString,
mainContext
)
)
: resource?.supportedProperty
? [
updatePropertiesAccordingToPath(
resource.supportedProperty,
pathWithoutQueryString,
mainContext
),
]
: resource?.supportedProperty,
}
}, [api, pathWithoutQueryString, mainContext, resourceName])
}
export function useResourceOperations<T extends IHydraMember>(
resource: IResource
): IResourceOperations<T> {
const { supportedOperation } = resource
const fetchApi = useApiFetch()
const apiUrl = getApiUrl(resource.url)
const update = useCallback(
(id: string | number, item: Partial<T>): Promise<T | IError> =>
fetchApi<T>(`${apiUrl}/${id}`, undefined, {
body: JSON.stringify(item),
method: Method.PATCH,
headers: { [contentTypeHeader]: 'application/merge-patch+json' },
}),
[apiUrl, fetchApi]
)
const create = useCallback(
(item: Omit<T, 'id' | '@id' | '@type'>): Promise<T | IError> => {
// Check if item is FormData (file upload)
const isFormData = item instanceof FormData
const requestOptions: RequestInit = {
body: isFormData ? item : JSON.stringify(item),
method: Method.POST,
headers: {
[contentTypeHeader]: isFormData ? '' : 'application/ld+json',
},
}
return fetchApi(apiUrl, undefined, requestOptions)
},
[apiUrl, fetchApi]
)
const replace = useCallback(
(item: Partial<T>): Promise<T | IError> =>
fetchApi(`${apiUrl}/${item.id}`, undefined, {
body: JSON.stringify(item),
method: Method.PUT,
}),
[apiUrl, fetchApi]
)
const remove = useCallback(
(id: string | number): Promise<T | IError> =>
fetchApi(`${apiUrl}/${id}`, undefined, {
method: Method.DELETE,
}),
[apiUrl, fetchApi]
)
return useMemo(
() =>
supportedOperation.reduce<IResourceOperations<T>>((acc, operation) => {
if (typeof operation['@type'] === 'string') {
acc.update = update
} else if (
operation['@type'] instanceof Array &&
operation['@type'].length === 2 &&
typeof operation['@type'][1] === 'string'
) {
if (
operation['@type'][1].indexOf('//schema.org/CreateAction') !== -1
) {
acc.create = create
} else if (
operation['@type'][1].indexOf('//schema.org/ReplaceAction') !== -1
) {
acc.replace = replace
} else if (
operation['@type'][1].indexOf('//schema.org/DeleteAction') !== -1
) {
acc.remove = remove
}
}
return acc
}, {}),
[create, remove, replace, supportedOperation, update]
)
}