@@ -0,0 +1,45 @@ | |||||
import { h, Component } from 'preact'; | |||||
import WBTable from 'wb-table'; | |||||
import WBBreadcrumbs from 'wb-breadcrumbs'; | |||||
import { WBManifestReader } from 'wb-collection-manifest'; | |||||
import makeArvadosRequest from 'make-arvados-request'; | |||||
class WBCollectionContent extends Component { | |||||
constructor(...args) { | |||||
super(...args); | |||||
this.state.path = '.'; | |||||
this.state.rows = []; | |||||
this.state.manifestReader = null; | |||||
} | |||||
componentDidMount() { | |||||
let { arvHost, arvToken } = this.props.app.state; | |||||
let { uuid } = this.props; | |||||
let select = [ 'manifest_text' ]; | |||||
let prom = makeArvadosRequest(arvHost, arvToken, | |||||
'/arvados/v1/collections/' + uuid + | |||||
'?select=' + encodeURIComponent(JSON.stringify(select))); | |||||
prom = prom.then(xhr => { | |||||
this.state.manifestReader = new WBManifestReader(xhr.response.manifest_text); | |||||
this.prepareRows(); | |||||
}); | |||||
} | |||||
prepareRows() { | |||||
this.setState({}); | |||||
} | |||||
render({}, { rows }) { | |||||
return ( | |||||
<div> | |||||
<WBBreadcrumbs items={ [ 'a', 'b', 'c' ] } /> | |||||
<WBTable columns={ [ 'Name', 'Size', 'Actions' ] } | |||||
rows={ rows } /> | |||||
</div> | |||||
); | |||||
} | |||||
} | |||||
export default WBCollectionContent; |
@@ -42,7 +42,7 @@ class WBArvadosCollection { | |||||
fileSizes = fileNames.map(n => fileSizes[n]); | fileSizes = fileNames.map(n => fileSizes[n]); | ||||
return [ streamName, fileNames, fileSizes ]; | return [ streamName, fileNames, fileSizes ]; | ||||
}); | }); | ||||
return this.content; | return this.content; | ||||
} | } | ||||
} | } | ||||
@@ -0,0 +1,114 @@ | |||||
class CMDirectory { | |||||
constructor() { | |||||
this.directories = {}; | |||||
this.files = {}; | |||||
} | |||||
} | |||||
class CMFile { | |||||
constructor() { | |||||
this.blockRefs = []; | |||||
this.size = 0; | |||||
} | |||||
append(locators, position, size) { | |||||
if (size === 0) | |||||
return; | |||||
let cum = 0; | |||||
let locHashes = locators.map(loc => loc[0]); | |||||
let locSizes = locators.map(loc => loc[1]); | |||||
let locPositions = locators.map(loc => { | |||||
let res = cum; | |||||
cum += loc[1]; | |||||
return res; | |||||
}); | |||||
let used = locators.map((_, i) => (locPositions[i] + locSizes[i] > position && | |||||
locPositions[i] < position + size)); | |||||
let startBlock = used.indexOf(true); | |||||
let endBlock = used.lastIndexOf(true) + 1; | |||||
console.log('startBlock: ' + startBlock + ', endBlock: ' + endBlock); | |||||
if (startBlock === -1) | |||||
return; | |||||
let blockRefs = []; | |||||
let runPos = position; | |||||
let runSize = size; | |||||
for (let i = startBlock; i < endBlock; i++) { | |||||
let blockPos = runPos - locPositions[i]; | |||||
let blockSize = Math.min(runSize, locSizes[i] - blockPos); | |||||
blockRefs.push([ locHashes[i], blockPos, blockSize ]); | |||||
runPos += blockSize; | |||||
runSize -= blockSize; | |||||
} | |||||
this.blockRefs = this.blockRefs.concat(blockRefs); | |||||
this.size += size; | |||||
} | |||||
} | |||||
class WBManifestReader { | |||||
constructor(manifest_text) { | |||||
this.rootDir = new CMDirectory(); | |||||
if (!manifest_text) | |||||
return; | |||||
this.parse(manifest_text); | |||||
} | |||||
makeDir(parent, name) { | |||||
if (!(name in parent.directories)) | |||||
parent.directories[name] = new CMDirectory(); | |||||
return parent.directories[name]; | |||||
} | |||||
makePath(path) { | |||||
if (typeof(path) === 'string') | |||||
path = path.split('/'); | |||||
let dir = this.rootDir; | |||||
for (let i = 1; i < path.length; i++) | |||||
dir = this.makeDir(dir, path[i]); | |||||
return dir; | |||||
} | |||||
appendFile(streamName, locators, position, size, fileName) { | |||||
let path = streamName + '/' + fileName; | |||||
path = path.split('/'); | |||||
let dir = this.makePath(path.slice(0, path.length - 1)); | |||||
if (!(fileName in dir.files)) | |||||
dir.files[fileName] = new CMFile(); | |||||
dir.files[fileName].append(locators, position, size); | |||||
} | |||||
parse(manifest_text) { | |||||
let rx = /^[a-f0-9]{32}\+[0-9]+/; | |||||
let streams = manifest_text.split('\n'); | |||||
streams.map(s => { | |||||
let tokens = s.split(' '); | |||||
let streamName = tokens[0]; | |||||
let n = tokens.map(t => rx.exec(t)); | |||||
n = n.indexOf(null, 1); | |||||
let locators = tokens.slice(1, n); | |||||
locators = locators.map(loc => [ loc, Number(loc.split('+')[1]) ]); | |||||
let fileTokens = tokens.slice(n); | |||||
fileTokens.map(t => { | |||||
let [ position, size, fileName ] = t.split(':'); | |||||
this.appendFile(streamName, locators, | |||||
Number(position), Number(size), fileName); | |||||
}); | |||||
}); | |||||
} | |||||
} | |||||
export { WBManifestReader }; |
@@ -5,6 +5,7 @@ import WBSignIn from 'wb-sign-in'; | |||||
import WBLandingPage from 'wb-landing-page'; | import WBLandingPage from 'wb-landing-page'; | ||||
import WBProcessView from 'wb-process-view'; | import WBProcessView from 'wb-process-view'; | ||||
import WBCollectionView from 'wb-collection-view'; | import WBCollectionView from 'wb-collection-view'; | ||||
import WBCollectionBrowse from 'wb-collection-browse'; | |||||
import arvadosTypeName from 'arvados-type-name'; | import arvadosTypeName from 'arvados-type-name'; | ||||
class WBApp extends Component { | class WBApp extends Component { | ||||
@@ -65,6 +66,8 @@ class WBApp extends Component { | |||||
<WBProcessView path="/process/:uuid" app={ this } /> | <WBProcessView path="/process/:uuid" app={ this } /> | ||||
<WBCollectionView path="/collection/:uuid" app={ this } /> | <WBCollectionView path="/collection/:uuid" app={ this } /> | ||||
<WBCollectionBrowse path='/collection-browse/:uuid' app={ this } /> | |||||
</Router> | </Router> | ||||
); | ); | ||||
} | } | ||||
@@ -0,0 +1,24 @@ | |||||
import { h, Component } from 'preact'; | |||||
import WBNavbarCommon from 'wb-navbar-common'; | |||||
import WBArvadosCrumbs from 'wb-arvados-crumbs'; | |||||
import WBCollectionContent from 'wb-collection-content'; | |||||
class WBCollectionBrowse extends Component { | |||||
render({ app, uuid }, {}) { | |||||
return ( | |||||
<div> | |||||
<WBNavbarCommon app={ app } /> | |||||
<WBArvadosCrumbs app={ app } uuid={ uuid } /> | |||||
<div class="my-2"> | |||||
This is the collection browser for { uuid } | |||||
</div> | |||||
<WBCollectionContent app={ app } uuid={ uuid } /> | |||||
</div> | |||||
); | |||||
} | |||||
} | |||||
export default WBCollectionBrowse; |