|
|
@@ -1,11 +1,115 @@ |
|
|
|
import { h, Component } from 'preact';
|
|
|
|
import WBManifestWorkerWrapper from 'wb-manifest-worker-wrapper';
|
|
|
|
import makeArvadosRequest from 'make-arvados-request';
|
|
|
|
import WBTable from 'wb-table';
|
|
|
|
import WBPagination from 'wb-pagination';
|
|
|
|
|
|
|
|
function unescapeName(name) {
|
|
|
|
return name.replace(/(\\\\|\\[0-9]{3})/g,
|
|
|
|
(_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8))));
|
|
|
|
}
|
|
|
|
|
|
|
|
class WBBrowseDialogCollectionContent extends Component {
|
|
|
|
render() {
|
|
|
|
constructor(...args) {
|
|
|
|
super(...args);
|
|
|
|
this.state.manifestWorker = new WBManifestWorkerWrapper();
|
|
|
|
this.state.mode = 'manifestDownload';
|
|
|
|
this.state.rows = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
const { app, collectionUuid } = this.props;
|
|
|
|
const { arvHost, arvToken } = app.state;
|
|
|
|
const { manifestWorker } = this.state;
|
|
|
|
|
|
|
|
let prom = makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/collections/' + collectionUuid);
|
|
|
|
|
|
|
|
let streams;
|
|
|
|
|
|
|
|
prom = prom.then(xhr => {
|
|
|
|
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));
|
|
|
|
});
|
|
|
|
|
|
|
|
return manifestWorker.postMessage([ 'precreatePaths', paths ]);
|
|
|
|
});
|
|
|
|
|
|
|
|
prom = prom.then(() => {
|
|
|
|
this.setState({ 'mode': 'manifestParse' });
|
|
|
|
let prom_1 = new Promise(accept => accept());
|
|
|
|
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]));
|
|
|
|
}
|
|
|
|
return prom_1;
|
|
|
|
});
|
|
|
|
|
|
|
|
prom = prom.then(() => manifestWorker.postMessage([ 'listDirectory', '.' + this.props.collectionPath, true ]));
|
|
|
|
prom = prom.then(e => {
|
|
|
|
this.state.mode = 'browsingReady';
|
|
|
|
this.prepareRows(e.data[1])
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
this.props = nextProps;
|
|
|
|
if (this.state.mode !== 'browsingReady')
|
|
|
|
return;
|
|
|
|
let prom = this.state.manifestWorker.postMessage([
|
|
|
|
'listDirectory', '.' + this.props.collectionPath, true
|
|
|
|
]);
|
|
|
|
prom = prom.then(e => this.prepareRows(e.data[1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
prepareRows(listing) {
|
|
|
|
const { makeSelectionCell, collectionPath, navigate,
|
|
|
|
page, itemsPerPage, collectionUuid, textSearch } = this.props;
|
|
|
|
const textLower = textSearch.toLowerCase();
|
|
|
|
listing = listing.filter(it => (it[1].toLowerCase().indexOf(textLower) !== -1));
|
|
|
|
const numPages = Math.ceil(listing.length / itemsPerPage);
|
|
|
|
const rows = listing.slice(page * itemsPerPage,
|
|
|
|
(page + 1) * itemsPerPage).map(it => [
|
|
|
|
makeSelectionCell(collectionUuid + '/' + collectionPath + '/' + it[1]),
|
|
|
|
it[0] === 'd' ? (
|
|
|
|
<a href="#" onclick={ e => {
|
|
|
|
e.preventDefault();
|
|
|
|
navigate({ 'collectionPath': collectionPath + '/' + it[1],
|
|
|
|
'bottomPage': 0 });
|
|
|
|
} }>{ it[1] }</a>
|
|
|
|
) : it[1],
|
|
|
|
it[0] === 'f' ? filesize(it[2]) : ''
|
|
|
|
]);
|
|
|
|
this.setState({ rows, numPages });
|
|
|
|
}
|
|
|
|
|
|
|
|
render({ page, navigate }, { rows, mode, numPages }) {
|
|
|
|
return (
|
|
|
|
<div>WBBrowseDialogCollectionContent</div>
|
|
|
|
<div>
|
|
|
|
{ mode === 'browsingReady' ? (
|
|
|
|
null
|
|
|
|
) : [
|
|
|
|
<div>{ mode === 'manifestParse' ? 'Parsing manifest...' : 'Downloading manifest...' }</div>,
|
|
|
|
<div class="progress my-2">
|
|
|
|
<div class={ 'progress-bar progress-bar-striped progress-bar-animated' +
|
|
|
|
(mode === 'manifestParse' ? ' bg-success': '') } role="progressbar"
|
|
|
|
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div>
|
|
|
|
</div>
|
|
|
|
] }
|
|
|
|
<WBTable headerClasses={ ['col-sm-1', 'col-sm-4', 'col-sm-4'] }
|
|
|
|
columns={ [ '', 'Name', 'Size' ] } rows={ rows } />
|
|
|
|
<WBPagination numPages={ numPages } activePage={ page }
|
|
|
|
onPageChanged={ i => navigate({ 'bottomPage': i }) } />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WBBrowseDialogCollectionContent.defaultProps = {
|
|
|
|
'itemsPerPage': 20
|
|
|
|
};
|
|
|
|
|
|
|
|
export default WBBrowseDialogCollectionContent;
|