Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | 27x | import { useCallback } from 'react';
import { useMutation, useQuery } from 'react-query';
import { useOkapiKy } from '@folio/stripes/core';
import { downloadBlob } from '../utils';
// This is copied and adapted from stripes-erm-components
const useFileHandlers = ({
// When fetchFile is true, will AUTOMATICALLY fetch not only
// fileMetadata but ALSO file itself
fetchFile = false,
/* fileEndpoint can be a string or
* {
* download: string | function,
* metadata: string | function
* upload: string | function,
* }
*/
fileEndpoint,
fileField = 'upload',
fileMappings = {}, // A mapping from file -> formData field,
fileId // An OPTIONAL id for a file which results in fetching and returning file metadata
}) => {
const ky = useOkapiKy();
// A method which resolves the endpoint to hit based on fileEndpoint
const resolveEndpoint = useCallback((type, file) => {
if (typeof fileEndpoint === 'string') {
// We have a base endpoint, configure default behaviour
switch (type) {
case 'upload':
return fileEndpoint;
case 'download':
return `${fileEndpoint}/${file?.id}/raw`;
case 'metadata':
return `${fileEndpoint}/${file.id}`;
default:
throw new TypeError(`Unsupported endpoint type ${type}`);
}
}
if (typeof fileEndpoint !== 'object') {
throw new TypeError(`Unsupported fileEndpoint type ${typeof fileEndpoint}`);
}
const config = fileEndpoint[type];
if (config === null) {
throw new TypeError(`Unsupported fileEndpoint[${type}] is not configured`);
}
// Finally we have configured behaviour
switch (typeof config) {
case 'function':
return config(file);
case 'string':
return config;
default:
// If we have hit the end then we've done something wrong
throw new TypeError(`Unsupported configuration for fileEndpoint[${type}]: ${typeof config}`);
}
}, [fileEndpoint]);
const { mutateAsync: handleUploadFile } = useMutation(
[fileEndpoint, 'handleUpload'],
(file) => {
const formData = new FormData();
formData.append(fileField, file);
Object.entries(fileMappings).forEach(([key, value]) => {
if (typeof value === 'string') {
formData.append(key, value);
} else if (typeof value === 'function') {
formData.append(key, value(file));
} else {
throw new TypeError('Invalid fileMapping: ' + key);
}
});
return ky.post(resolveEndpoint('upload', file), { body: formData }).json();
}
);
const {
data: fileBlob,
isLoading: isFileLoading,
refetch: refetchFile
} = useQuery({
queryKey: [fileEndpoint, 'content', fileId],
queryFn: () => ky.get(resolveEndpoint('download', { id: fileId })).blob(),
enabled: !!fileId && typeof fileId === 'string' && fetchFile,
staleTime: Infinity, // Assume the file won't change underneath us.
});
// We are declaratively fetching a file via a function, useMutation is more convenient here
// NOTE even if fileBlob already exists this will refetch it for download
const { mutate: getFile, mutateAsync: getFileAsync } = useMutation(
[fileEndpoint, 'getFile'],
(file) => ky.get(resolveEndpoint('download', file)).blob()
);
const handleDownloadFile = useCallback((fileMetadata) => {
return getFileAsync(fileMetadata)
/* In this instance we want the file name back as it was handed in, whitespace and all */
.then(downloadBlob(fileMetadata.name, { processWhitespace: false }));
}, [getFileAsync]);
const { data: fileMetadata, isLoading: isFileMetadataLoading } = useQuery({
queryKey: [fileEndpoint, 'metadata', fileId],
queryFn: () => ky.get(resolveEndpoint('metadata', { id: fileId })).json(),
enabled: !!fileId && typeof fileId === 'string',
});
return {
file: fileBlob,
fileMetadata,
getFile,
getFileAsync,
handleDownloadFile,
handleUploadFile,
isFileLoading,
isFileMetadataLoading,
refetchFile
};
};
export default useFileHandlers;
|