|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- 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') ? [
- (<a href={ this.getUrl({ 'collectionPath': collectionPath + '/' + item[1], 'page': 0 }) }>{ item[1] }/</a>),
- 'Directory',
- null,
- (<div></div>)
- ] : [
- item[1],
- 'File',
- filesize(item[2]),
- ( (mode === 'browsingReady') ? (
- <div>
- <button class="btn btn-outline-primary mx-1" title="Download"
- onclick={ () => manifestWorker.postMessage([ 'getFile',
- '.' + collectionPath + '/' + item[1] ]).then(e => {
- const file = e.data[1];
- const blob = new Blob([
- JSON.stringify([ arvHost, arvToken, item[1], file ])
- ]);
- const blocksBlobUrl = URL.createObjectURL(blob);
- window.open('/download/' + encodeURIComponent(blocksBlobUrl), '_blank');
-
- }) }><i class="fas fa-download"></i></button>
-
- <button class="btn btn-outline-primary mx-1" title="View"
- onclick={ () => {
- alert('Not implemented.')
- } }><i class="far fa-eye"></i></button>
-
- { item[1].toLowerCase().endsWith('.nii') ? (
- <button class="btn btn-outline-primary mx-1" title="View Image"
- onclick={ () => manifestWorker.postMessage([ 'getFile',
- '.' + collectionPath + '/' + item[1] ]).then(e => {
- const file = e.data[1];
- const blob = new Blob([
- JSON.stringify({ 'name': item[1], 'file': file })
- ]);
- const blocksBlobUrl = URL.createObjectURL(blob);
- window.open('/image-viewer/' + encodeURIComponent(blocksBlobUrl), '_blank');
-
- }) }><i class="far fa-eye"></i></button>
- ) : null }
- </div>
- ) : null)
- ]
- ))
- });
- }
-
- render({ collectionPath, page }, { manifestReader, rows,
- numPages, loaded, total, mode, parsedStreams, totalStreams }) {
-
- return (
- <div>
- <WBBreadcrumbs items={ ('.' + collectionPath).split('/') } />
-
- { (mode === 'manifestDownload') ?
- (
- <div class="container-fluid">
- <div>Downloading manifest: { filesize(loaded) }</div>
- <div class="progress">
- <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar"
- aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div>
- </div>
- </div>
-
- ) : (
- <div>
- { mode === 'manifestParse' ? (
- <div class="container-fluid mb-2">
- <div>Parsing manifest: { parsedStreams }/{ totalStreams }</div>
- <div class="progress">
- <div class="progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar"
- aria-valuenow={ totalStreams } aria-valuemin="0" aria-valuemax={ parsedStreams } style={ 'width: ' + Math.round(parsedStreams * 100 / totalStreams) + '%' }></div>
- </div>
- </div>
- ) : null }
-
- <WBTable columns={ [ 'Name', 'Type', 'Size', 'Actions' ] }
- rows={ rows } />
-
- <WBPagination activePage={ page } numPages={ numPages }
- getPageUrl={ page => this.getUrl({ 'page': page }) } />
- </div>
- ) }
- </div>
- );
- }
- }
-
- WBCollectionContent.defaultProps = {
- 'collectionPath': '',
- 'page': 0,
- 'itemsPerPage': 20
- };
-
- export default WBCollectionContent;
|