diff --git a/frontend/src/js/component/wb-collection-content.js b/frontend/src/js/component/wb-collection-content.js
index 31f5816..49c876a 100644
--- a/frontend/src/js/component/wb-collection-content.js
+++ b/frontend/src/js/component/wb-collection-content.js
@@ -7,11 +7,18 @@ import makeArvadosRequest from 'make-arvados-request';
class WBCollectionContent extends Component {
constructor(...args) {
super(...args);
- this.state.path = '.';
this.state.rows = [];
this.state.manifestReader = null;
}
+ getUrl(params) {
+ let res = '/collection-browse/' +
+ (params.uuid || this.props.uuid) + '/' +
+ encodeURIComponent(params.collectionPath || this.props.collectionPath) + '/' +
+ (params.page || this.props.page);
+ return res;
+ }
+
componentDidMount() {
let { arvHost, arvToken } = this.props.app.state;
let { uuid } = this.props;
@@ -26,20 +33,52 @@ class WBCollectionContent extends Component {
});
}
+ componentWillReceiveProps(nextProps) {
+ this.props = nextProps;
+ this.prepareRows();
+ }
+
prepareRows() {
- this.setState({});
+ let { manifestReader } = this.state;
+ let { collectionPath } = this.props;
+
+ //path = path.split('/');
+ //path = [ '.' ].concat(path);
+
+ let listing = manifestReader.listDirectory('.' + collectionPath);
+
+ this.setState({
+ 'rows': listing.map(item => (
+ (item[0] === 'd') ? [
+ ({ item[1] }/),
+ 'Directory',
+ null,
+ (
)
+ ] : [
+ ({ item[1] }),
+ 'File',
+ filesize(item[2]),
+ ()
+ ]
+ ))
+ });
}
- render({}, { rows }) {
+ render({ collectionPath }, { rows }) {
return (
-
+
-
);
}
}
+WBCollectionContent.defaultProps = {
+ 'collectionPath': '',
+ 'page': 0
+};
+
export default WBCollectionContent;
diff --git a/frontend/src/js/misc/wb-collection-manifest.js b/frontend/src/js/misc/wb-collection-manifest.js
index 704cc9d..904984f 100644
--- a/frontend/src/js/misc/wb-collection-manifest.js
+++ b/frontend/src/js/misc/wb-collection-manifest.js
@@ -1,17 +1,52 @@
-class CMDirectory {
- constructor() {
- this.directories = {};
- this.files = {};
+//
+// Directory: Hash[string, [Directory, File]]
+// File = [blockRefs, size]
+// blockRefs: Array[blockRef]
+// blockRef: [locator, position, size]
+// locator: String
+// position: Number
+// size: Number
+//
+
+class WBManifestReader {
+ constructor(manifest_text) {
+ this.rootDir = {};
+
+ if (!manifest_text)
+ return;
+
+ this.parse(manifest_text);
+ }
+
+ makeDir(parent, name) {
+ if (!(name in parent))
+ parent[name] = {};
+ if (parent[name] instanceof Array)
+ throw Error('Conflict trying to create a directory - a file with the same name already exists: ' + name);
+ return parent[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;
}
-}
-class CMFile {
- constructor() {
- this.blockRefs = [];
- this.size = 0;
+ 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))
+ dir[fileName] = [[], 0];
+ if (!(dir[fileName] instanceof Array))
+ throw Error('Conflict trying to create a file - a directory with the same name already exists: ' + fileName);
+ this.appendReferences(dir[fileName], locators, position, size);
}
- append(locators, position, size) {
+ appendReferences(file, locators, position, size) {
if (size === 0)
return;
@@ -30,7 +65,7 @@ class CMFile {
let startBlock = used.indexOf(true);
let endBlock = used.lastIndexOf(true) + 1;
- console.log('startBlock: ' + startBlock + ', endBlock: ' + endBlock);
+ // console.log('startBlock: ' + startBlock + ', endBlock: ' + endBlock);
if (startBlock === -1)
return;
@@ -47,53 +82,20 @@ class CMFile {
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);
+ file[0] = file[0].concat(blockRefs);
+ file[1] += size;
}
parse(manifest_text) {
let rx = /^[a-f0-9]{32}\+[0-9]+/;
let streams = manifest_text.split('\n');
+ if (!streams[streams.length - 1])
+ streams = streams.slice(0, streams.length - 1);
streams.map(s => {
let tokens = s.split(' ');
- let streamName = tokens[0];
+ let streamName = this.unescapeName(tokens[0]);
let n = tokens.map(t => rx.exec(t));
n = n.indexOf(null, 1);
@@ -104,11 +106,61 @@ class WBManifestReader {
let fileTokens = tokens.slice(n);
fileTokens.map(t => {
let [ position, size, fileName ] = t.split(':');
+ fileName = this.unescapeName(fileName);
this.appendFile(streamName, locators,
Number(position), Number(size), fileName);
});
});
}
+
+ findDir(path) {
+ if (typeof(path) === 'string')
+ path = path.split('/');
+ if (path[0] !== '.')
+ throw Error('Path must begin with a dot component');
+ let dir = this.rootDir;
+ for (let i = 1; i < path.length; i++) {
+ if (!(path[i] in dir))
+ throw Error('Directory not found');
+ if (dir[path[i]] instanceof Array)
+ throw Error('Path is a file not directory');
+ dir = dir[path[i]];
+ }
+ return dir;
+ }
+
+ listDirectory(path) {
+ let dir = this.findDir(path);
+ let keys = Object.keys(dir);
+ keys.sort();
+ let subdirs = keys.filter(k => !(dir[k] instanceof Array));
+ let files = keys.filter(k => (dir[k] instanceof Array));
+ let res = subdirs.map(k => [ 'd', k, null ]);
+ res = res.concat(files.map(k => [ 'f', k, dir[k][1] ]));
+ return res;
+ }
+
+ unescapeName(name) {
+ return name.replace(/(\\\\|\\040)/g, (_, $1) => ($1 === '\\\\' ? '\\' : ' '));
+ }
+
+ escapeName(name) {
+ return name.replace(/ /g, '\\040');
+ }
+ /* let ids = { '\\': 1, '0': 2, '4': 3 };
+ let transitions = [
+ [ [0, 0], [1, ''], [0, 0], [0, 0] ],
+ [ [0, 0], [0, '\\'], [2, ''], [0, 0] ],
+ ];
+ let mode = 0;
+ for (let i = 0; i < name.length; i++) {
+ let b = name[i];
+ let tokenId = Number(ids[b]);
+ [ mode, out ] = transitions[mode][tokenId];
+ if (out === 0)
+ out = b;
+ }
+ }*/
}
export { WBManifestReader };
diff --git a/frontend/src/js/page/wb-app.js b/frontend/src/js/page/wb-app.js
index ea554fb..4718dca 100644
--- a/frontend/src/js/page/wb-app.js
+++ b/frontend/src/js/page/wb-app.js
@@ -67,7 +67,7 @@ class WBApp extends Component {
-
+
);
}
diff --git a/frontend/src/js/page/wb-collection-browse.js b/frontend/src/js/page/wb-collection-browse.js
index e238702..d92cd86 100644
--- a/frontend/src/js/page/wb-collection-browse.js
+++ b/frontend/src/js/page/wb-collection-browse.js
@@ -4,7 +4,7 @@ import WBArvadosCrumbs from 'wb-arvados-crumbs';
import WBCollectionContent from 'wb-collection-content';
class WBCollectionBrowse extends Component {
- render({ app, uuid }, {}) {
+ render({ app, uuid, collectionPath }, {}) {
return (
@@ -15,7 +15,8 @@ class WBCollectionBrowse extends Component {
This is the collection browser for { uuid }
-
+
);
}