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.

116 lines
4.1KB

  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 } = 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. makeSelectionCell(collectionUuid + '/' + collectionPath + '/' + it[1]),
  66. it[0] === 'd' ? (
  67. <a href="#" onclick={ e => {
  68. e.preventDefault();
  69. navigate({ 'collectionPath': collectionPath + '/' + it[1],
  70. 'bottomPage': 0 });
  71. } }>{ it[1] }</a>
  72. ) : it[1],
  73. it[0] === 'f' ? filesize(it[2]) : ''
  74. ]);
  75. this.setState({ rows, numPages });
  76. }
  77. render({ page, navigate }, { rows, mode, numPages }) {
  78. return (
  79. <div>
  80. { mode === 'browsingReady' ? (
  81. null
  82. ) : [
  83. <div>{ mode === 'manifestParse' ? 'Parsing manifest...' : 'Downloading manifest...' }</div>,
  84. <div class="progress my-2">
  85. <div class={ 'progress-bar progress-bar-striped progress-bar-animated' +
  86. (mode === 'manifestParse' ? ' bg-success': '') } role="progressbar"
  87. aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div>
  88. </div>
  89. ] }
  90. <WBTable headerClasses={ ['col-sm-1', 'col-sm-4', 'col-sm-4'] }
  91. columns={ [ '', 'Name', 'Size' ] } rows={ rows } />
  92. <WBPagination numPages={ numPages } activePage={ page }
  93. onPageChanged={ i => navigate({ 'bottomPage': i }) } />
  94. </div>
  95. );
  96. }
  97. }
  98. WBBrowseDialogCollectionContent.defaultProps = {
  99. 'itemsPerPage': 20
  100. };
  101. export default WBBrowseDialogCollectionContent;