Created
March 24, 2021 14:28
-
-
Save Manoj-nathwani/726615bcf0f3b9900b51cf14be618952 to your computer and use it in GitHub Desktop.
BulkFileUploaderComponent
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ReactDOM from 'react-dom'; | |
import React from 'react'; | |
import App from './src/App'; | |
const componentElement = | |
document.getElementById('BulkFileUploaderComponent'); | |
const getAttr = key => { | |
const val = componentElement.getAttribute(`data-${key}`); | |
return ['None', ''].includes(val) ? null : val; | |
}; | |
const requiredString = str => { | |
console.assert(str.length); | |
return str; | |
} | |
const | |
lfsServer = requiredString(getAttr('lfsServer')), | |
orgId = requiredString(getAttr('orgId')), | |
datasetId = requiredString(getAttr('datasetId')); | |
// wait for ckan.i18n to load | |
window.addEventListener('load', function () { | |
ReactDOM.render( | |
<App {...{ lfsServer, orgId, datasetId }} />, | |
componentElement | |
); | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect } from 'react'; | |
import { Promise } from 'bluebird'; | |
import axios from 'axios'; | |
import FileUploader from './FileUploader'; | |
export default function App({ lfsServer, orgId, datasetId }) { | |
const axiosHeaders = { | |
'Authorization': '<YOUR CKAN API KEY>' | |
}; | |
const [authToken, setAuthToken] = useState(); | |
useEffect(() => { | |
axios.post( | |
'/api/3/action/authz_authorize', | |
{ scopes: `obj:ckan/${datasetId}/*:write` }, | |
{ withCredentials: true } | |
) | |
.then(res => setAuthToken(res.data.result.token)) | |
.catch(error => { | |
console.log(`authz_authorize error: ${error}`); | |
setAuthToken('error') | |
}) | |
}, []); | |
if (!authToken) return 'Loading...'; | |
const handleFilesSelected = file => { | |
const files = [file]; | |
// ckan can't handle concurrent resource uploads, | |
// so we're sequentially uploading each one | |
Promise.mapSeries(files, derp => ( | |
axios({ | |
method: 'POST', | |
url: 'http://dev-adr/api/3/action/resource_create', | |
data: { | |
package_id: datasetId, | |
url_type: 'upload', | |
name: file.name, | |
sha256: file.sha256, | |
size: file.size, | |
url: file.name, | |
lfs_prefix: `${orgId}/${datasetId}`, | |
}, | |
headers: axiosHeaders | |
}) | |
)).then(() => window.location.replace(window.location.pathname)) | |
} | |
const handleDelete = () => { | |
axios({ | |
method: 'GET', | |
url: 'http://dev-adr/api/3/action/package_show', | |
params: { id: datasetId }, | |
headers: axiosHeaders | |
}).then(res => { | |
Promise.mapSeries(res.data.result.resources, resource => ( | |
axios({ | |
method: 'POST', | |
url: 'http://dev-adr/api/3/action/resource_delete', | |
data: { id: resource.id }, | |
headers: axiosHeaders | |
}) | |
)).then(() => window.location.replace(window.location.pathname)); | |
}); | |
} | |
return ( | |
<> | |
<FileUploader {...{ | |
lfsServer, orgId, datasetId, authToken, | |
handleFilesSelected | |
}} /> | |
<button className="btn btn-default pull-right" onClick={handleDelete}>🔥 Delete all resources</button> | |
</> | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { useDropzone } from 'react-dropzone' | |
import { Client } from 'giftless-client'; | |
export default function FileUploader({ | |
lfsServer, orgId, datasetId, authToken, handleFilesSelected | |
}) { | |
const handleFileSelected = async inputFile => { | |
if (!inputFile) return; | |
const file = data.open(inputFile); | |
const client = new Client(lfsServer, authToken, ['basic']); | |
await client.upload(file, orgId, datasetId); | |
console.log(file); | |
handleFilesSelected({ | |
name: file._descriptor.name, | |
sha256: file._computedHashes.sha256, | |
size: file._descriptor.size, | |
url: file._descriptor.name | |
}) | |
} | |
const { getRootProps, getInputProps, open } = useDropzone({ | |
multiple: false, | |
noClick: true, | |
onDrop: acceptedFiles => | |
handleFileSelected(acceptedFiles[0]), | |
onDropRejected: rejectedFiles => | |
handleFileSelected(rejectedFiles[0].file), | |
}) | |
const uploadOptions = [ | |
{ | |
name: 'FileUploaderButton', | |
label: ckan.i18n._('Upload a file'), | |
icon: 'fa-cloud-upload', | |
onClick: e => { | |
open(e); | |
e.preventDefault(); | |
} | |
} | |
] | |
return ( | |
<div {...getRootProps({ className: 'dropzone' })} data-testid="FileUploaderComponent"> | |
<input {...getInputProps()} data-testid="FileUploaderInput" /> | |
<p>{ckan.i18n._('Drag a file into this box or')}</p> | |
<div className="btn-group"> | |
{uploadOptions.map(option => ( | |
<button | |
key={option.name} | |
data-testid={option.name} | |
className="btn btn-default" | |
onClick={option.onClick} | |
> | |
<i className={`fa ${option.icon}`}></i> | |
{option.label} | |
</button> | |
))} | |
</div> | |
</div> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment