import { h, Component } from 'preact'; import WBTable from 'wb-table'; import WBBreadcrumbs from 'wb-breadcrumbs'; import WBPagination from 'wb-pagination'; import makeArvadosRequest from 'make-arvados-request'; import wbDownloadFile from 'wb-download-file'; import WBManifestWorkerWrapper from 'wb-manifest-worker-wrapper'; function unescapeName(name) { return name.replace(/(\\\\|\\[0-9]{3})/g, (_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8)))); } class WBCollectionContent extends Component { constructor(...args) { super(...args); this.state.rows = []; this.state.manifestWorker = new WBManifestWorkerWrapper(); this.state.loaded = 0; this.state.total = 0; this.state.mode = 'manifestDownload'; this.state.parsedStreams = 0; this.state.totalStreams = 1; } getUrl(params) { let res = '/collection-browse/' + ('uuid' in params ? params.uuid : this.props.uuid) + '/' + encodeURIComponent('collectionPath' in params ? params.collectionPath : this.props.collectionPath) + '/' + ('page' in params ? params.page : this.props.page); return res; } componentDidMount() { let { arvHost, arvToken } = this.props.app.state; let { uuid, collectionPath } = this.props; let { manifestWorker } = this.state; let select = [ 'manifest_text' ]; let prom = makeArvadosRequest(arvHost, arvToken, '/arvados/v1/collections/' + uuid + '?select=' + encodeURIComponent(JSON.stringify(select)), { 'onProgress': e => { this.setState({ 'loaded': e.loaded, 'total': e.total }); } }); prom = prom.then(xhr => { const streams = xhr.response.manifest_text.split('\n'); const paths = streams.filter(s => s).map(s => { const n = s.indexOf(' '); return unescapeName(s.substr(0, n)); }); let prom_1 = new Promise(accept => accept()); prom_1 = prom_1.then(() => { this.setState({ 'totalStreams': streams.length, 'parsedStreams': 0, 'mode': 'manifestParse' }); return manifestWorker.postMessage([ 'precreatePaths', paths ]); }); for (let i = 0; i < streams.length; i++) { prom_1 = prom_1.then(() => manifestWorker.postMessage([ 'parseStream', streams[i] ])); prom_1 = prom_1.then(() => manifestWorker.postMessage([ 'listDirectory', '.' + this.props.collectionPath, true ])); prom_1 = prom_1.then(e => { this.prepareRows(e.data[1]); this.setState({ 'parsedStreams': (i + 1) }); }); } prom_1 = prom_1.then(() => manifestWorker.postMessage([ 'listDirectory', '.' + this.props.collectionPath, true ])); prom_1 = prom_1.then(e => { this.state.mode = 'browsingReady'; this.prepareRows(e.data[1]); }); return prom_1; }); } componentWillReceiveProps(nextProps) { this.props = nextProps; const { manifestWorker, mode } = this.state; const { collectionPath } = this.props; if (mode === 'browsingReady') { let prom = manifestWorker.postMessage([ 'listDirectory', '.' + collectionPath, true ]); prom = prom.then(e => this.prepareRows(e.data[1])); } } prepareRows(listing) { let { manifestWorker, mode } = this.state; let { collectionPath, page, itemsPerPage, app } = this.props; let { arvHost, arvToken } = app.state; const numPages = Math.ceil(listing.length / itemsPerPage); listing = listing.slice(page * itemsPerPage, page * itemsPerPage + itemsPerPage); this.setState({ 'numPages': numPages, 'rows': listing.map(item => ( (item[0] === 'd') ? [ ({ item[1] }/), 'Directory', null, (
) ] : [ item[1], 'File', filesize(item[2]), ( (mode === 'browsingReady') ? (
{ item[1].toLowerCase().endsWith('.nii') ? ( ) : null }
) : null) ] )) }); } render({ collectionPath, page }, { manifestReader, rows, numPages, loaded, total, mode, parsedStreams, totalStreams }) { return (
{ (mode === 'manifestDownload') ? (
Downloading manifest: { filesize(loaded) }
) : (
{ mode === 'manifestParse' ? (
Parsing manifest: { parsedStreams }/{ totalStreams }
) : null } this.getUrl({ 'page': page }) } />
) }
); } } WBCollectionContent.defaultProps = { 'collectionPath': '', 'page': 0, 'itemsPerPage': 20 }; export default WBCollectionContent;