import { h, Component } from 'preact'; import WBTable from 'wb-table'; import WBBreadcrumbs from 'wb-breadcrumbs'; import WBPagination from 'wb-pagination'; import WBRootDirWrapper from 'wb-rootdir-wrapper'; import makeArvadosRequest from 'make-arvados-request'; import wbDownloadFile from 'wb-download-file'; 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 Worker('/js/wb-manifest-worker.js'); this.state.manifestWorker.onerror = (e => console.log(e)); this.state.loaded = 0; this.state.total = 0; this.state.mode = 'manifestDownload'; this.state.parsedStreams = 0; this.state.totalStreams = 1; this.state.rootDirWrapper = null; } 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(() => { const prom_2 = new Promise(accept => { manifestWorker.onmessage = () => accept(); manifestWorker.postMessage([ 'precreatePaths', paths ]); this.setState({ 'totalStreams': streams.length, 'parsedStreams': 0, 'mode': 'manifestParse' }) }) return prom_2; }); for (let i = 0; i < streams.length; i++) { prom_1 = prom_1.then(() => { const prom_2 = new Promise(accept => { manifestWorker.onmessage = () => accept(); manifestWorker.postMessage([ 'parseStream', streams[i] ]); }); return prom_2; }); prom_1 = prom_1.then(() => { const prom_2 = new Promise(accept => { manifestWorker.onmessage = (e) => accept(e); manifestWorker.postMessage([ 'listDirectory', '.' + this.props.collectionPath, true ]); if (i % 1000 === 0) console.log(i + '/' + streams.length); }); return prom_2; }); prom_1 = prom_1.then(e => { this.prepareRows(e.data[1]); this.setState({ 'parsedStreams': (i + 1) }); }); } prom_1 = prom_1.then(() => { const prom_2 = new Promise(accept => { manifestWorker.onmessage = e => accept(e); manifestWorker.postMessage([ 'getData' ]); }); return prom_2; }); prom_1 = prom_1.then(e => { this.state.rootDirWrapper = new WBRootDirWrapper(e.data[1], e.data[2]); this.setState({ 'mode': 'browsingReady' }); this.prepareRows(this.state.rootDirWrapper.listDirectory('.' + this.props.collectionPath)); }); return prom_1; }); } componentWillReceiveProps(nextProps) { this.props = nextProps; const { rootDirWrapper, mode } = this.state; const { collectionPath } = this.props; if (mode === 'browsingReady') { const listing = rootDirWrapper.listDirectory('.' + collectionPath); this.prepareRows(listing); } } prepareRows(listing) { let { rootDirWrapper, 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') ? (