IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
4.3KB

  1. import { h, Component } from 'preact';
  2. import WBManifestWorkerWrapper from 'wb-manifest-worker-wrapper';
  3. import makeArvadosRequest from 'make-arvados-request';
  4. import WBTable from 'wb-table';
  5. import WBPagination from 'wb-pagination';
  6. function unescapeName(name) {
  7. return name.replace(/(\\\\|\\[0-9]{3})/g,
  8. (_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8))));
  9. }
  10. class WBBrowseDialogCollectionContent extends Component {
  11. constructor(...args) {
  12. super(...args);
  13. this.state.manifestWorker = new WBManifestWorkerWrapper();
  14. this.state.mode = 'manifestDownload';
  15. this.state.rows = [];
  16. }
  17. componentDidMount() {
  18. const { app, collectionUuid } = this.props;
  19. const { arvHost, arvToken } = app.state;
  20. const { manifestWorker } = this.state;
  21. let prom = makeArvadosRequest(arvHost, arvToken,
  22. '/arvados/v1/collections/' + collectionUuid);
  23. let streams;
  24. prom = prom.then(xhr => {
  25. streams = xhr.response.manifest_text.split('\n');
  26. const paths = streams.filter(s => s).map(s => {
  27. const n = s.indexOf(' ');
  28. return unescapeName(s.substr(0, n));
  29. });
  30. return manifestWorker.postMessage([ 'precreatePaths', paths ]);
  31. });
  32. prom = prom.then(() => {
  33. this.setState({ 'mode': 'manifestParse' });
  34. let prom_1 = new Promise(accept => accept());
  35. for (let i = 0; i < streams.length; i++) {
  36. prom_1 = prom_1.then(() => manifestWorker.postMessage([ 'parseStream', streams[i] ]));
  37. prom_1 = prom_1.then(() => manifestWorker.postMessage([ 'listDirectory', '.' + this.props.collectionPath, true ]));
  38. prom_1 = prom_1.then(e => this.prepareRows(e.data[1]));
  39. }
  40. return prom_1;
  41. });
  42. prom = prom.then(() => manifestWorker.postMessage([ 'listDirectory', '.' + this.props.collectionPath, true ]));
  43. prom = prom.then(e => {
  44. this.state.mode = 'browsingReady';
  45. this.prepareRows(e.data[1])
  46. });
  47. }
  48. componentWillReceiveProps(nextProps) {
  49. this.props = nextProps;
  50. if (this.state.mode !== 'browsingReady')
  51. return;
  52. let prom = this.state.manifestWorker.postMessage([
  53. 'listDirectory', '.' + this.props.collectionPath, true
  54. ]);
  55. prom = prom.then(e => this.prepareRows(e.data[1]));
  56. }
  57. prepareRows(listing) {
  58. const { makeSelectionCell, collectionPath, navigate,
  59. page, itemsPerPage, collectionUuid, textSearch, selectWhat } = this.props;
  60. const textLower = textSearch.toLowerCase();
  61. listing = listing.filter(it => (it[1].toLowerCase().indexOf(textLower) !== -1));
  62. const numPages = Math.ceil(listing.length / itemsPerPage);
  63. const rows = listing.slice(page * itemsPerPage,
  64. (page + 1) * itemsPerPage).map(it => [
  65. ((it[0] === 'd' && [].concat(selectWhat).indexOf('directory') !== -1) ||
  66. (it[0] === 'f' && [].concat(selectWhat).indexOf('file') !== -1)) ?
  67. makeSelectionCell(collectionUuid + collectionPath + '/' + it[1] + (it[0] === 'd' ? '/' : '')) :
  68. null,
  69. it[0] === 'd' ? (
  70. <a href="#" onclick={ e => {
  71. e.preventDefault();
  72. navigate({ 'collectionPath': collectionPath + '/' + it[1],
  73. 'bottomPage': 0 });
  74. } }>{ it[1] }</a>
  75. ) : it[1],
  76. it[0] === 'f' ? filesize(it[2]) : ''
  77. ]);
  78. this.setState({ rows, numPages });
  79. }
  80. render({ page, navigate }, { rows, mode, numPages }) {
  81. return (
  82. <div>
  83. { mode === 'browsingReady' ? (
  84. null
  85. ) : [
  86. <div>{ mode === 'manifestParse' ? 'Parsing manifest...' : 'Downloading manifest...' }</div>,
  87. <div class="progress my-2">
  88. <div class={ 'progress-bar progress-bar-striped progress-bar-animated' +
  89. (mode === 'manifestParse' ? ' bg-success': '') } role="progressbar"
  90. aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div>
  91. </div>
  92. ] }
  93. <WBTable headerClasses={ [ 'w-1' ] }
  94. columns={ [ '', 'Name', 'Size' ] } rows={ rows } />
  95. <WBPagination numPages={ numPages } activePage={ page }
  96. onPageChanged={ i => navigate({ 'bottomPage': i }) } />
  97. </div>
  98. );
  99. }
  100. }
  101. WBBrowseDialogCollectionContent.defaultProps = {
  102. 'itemsPerPage': 20
  103. };
  104. export default WBBrowseDialogCollectionContent;