diff --git a/frontend/src/js/arvados/process/wb-input-spec-info.js b/frontend/src/js/arvados/process/wb-input-spec-info.js
new file mode 100644
index 0000000..338b707
--- /dev/null
+++ b/frontend/src/js/arvados/process/wb-input-spec-info.js
@@ -0,0 +1,14 @@
+function wbInputSpecInfo(inputSpec) {
+ const isFile = (inputSpec.type === 'File' || inputSpec.type === 'File[]' ||
+ (inputSpec.type.type === 'array' && [].concat(inputSpec.type.items).indexOf('File') !== -1));
+
+ const isDirectory = (inputSpec.type === 'Directory' || inputSpec.type === 'Directory[]' ||
+ (inputSpec.type.type === 'array' && [].concat(inputSpec.type.items).indexOf('Directory') !== -1));
+
+ const isArray = (inputSpec.type === 'File[]' || inputSpec.type === 'Directory[]' ||
+ inputSpec.type.type === 'array');
+
+ return { isFile, isDirectory, isArray };
+}
+
+export default wbInputSpecInfo;
diff --git a/frontend/src/js/arvados/process/wb-parse-workflow-def.js b/frontend/src/js/arvados/process/wb-parse-workflow-def.js
new file mode 100644
index 0000000..2644c9f
--- /dev/null
+++ b/frontend/src/js/arvados/process/wb-parse-workflow-def.js
@@ -0,0 +1,11 @@
+function wbParseWorkflowDef(text) {
+ let definition;
+ try {
+ definition = JSON.parse(text);
+ } catch (_) {
+ definition = jsyaml.load(text);
+ }
+ return definition;
+}
+
+export default wbParseWorkflowDef;
diff --git a/frontend/src/js/arvados/process/wb-process-misc.js b/frontend/src/js/arvados/process/wb-process-misc.js
new file mode 100644
index 0000000..9cd06e6
--- /dev/null
+++ b/frontend/src/js/arvados/process/wb-process-misc.js
@@ -0,0 +1,11 @@
+function encodeURIComponentIncludingDots(s) {
+ return encodeURIComponent(s).replace('.', '%2E');
+}
+
+function parseKeepRef(value) {
+ if (typeof(value) === 'object' && 'location' in value && value.location.startsWith('keep:'))
+ return value.location.substr(5);
+ return value;
+}
+
+export { encodeURIComponentIncludingDots, parseKeepRef }
diff --git a/frontend/src/js/arvados/process/wb-uuids-to-cwl.js b/frontend/src/js/arvados/process/wb-uuids-to-cwl.js
new file mode 100644
index 0000000..6c0a3ff
--- /dev/null
+++ b/frontend/src/js/arvados/process/wb-uuids-to-cwl.js
@@ -0,0 +1,25 @@
+function wbUuidsToCwl(obj) {
+ if (obj instanceof Array) {
+ const res = [];
+ for (let k in obj) {
+ res[k] = uuidsToCwl(obj[k]);
+ }
+ return res;
+ }
+
+ if (typeof(obj) === 'string' &&
+ (/^[0-9a-z]{5}-[0-9a-z]{5}-[0-9a-z]{15}/.exec(obj) ||
+ /^[0-9a-f]{32}\+[0-9]+/.exec(obj))) {
+
+ const isDirectory = obj.endsWith('/');
+
+ return {
+ 'class': (isDirectory ? 'Directory' : 'File'),
+ 'location': 'keep:' + (isDirectory ? obj.substr(0, obj.length - 1) : obj)
+ };
+ }
+
+ throw Error('Expected Arvados path or array of paths');
+}
+
+export default wbUuidsToCwl;
diff --git a/frontend/src/js/component/wb-path-display.js b/frontend/src/js/component/wb-path-display.js
new file mode 100644
index 0000000..91706c3
--- /dev/null
+++ b/frontend/src/js/component/wb-path-display.js
@@ -0,0 +1,53 @@
+import { h, Component } from 'preact';
+import makeArvadosRequest from 'make-arvados-request';
+import { encodeURIComponentIncludingDots } from 'wb-process-misc';
+
+class WBPathDisplay extends Component {
+ fetchData() {
+ const { app } = this.props;
+ const { arvHost, arvToken } = app.state;
+ let { path } = this.props;
+ if (path.endsWith('/'))
+ path = path.substr(0, path.length - 1);
+ let m;
+ if (m = /^[0-9a-f]{32}\+[0-9]+/.exec(path));
+ else if (m = /^[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}/.exec(path));
+ else return;
+ let prom = makeArvadosRequest(arvHost, arvToken,
+ '/arvados/v1/collections/' + m[0]);
+ prom = prom.then(xhr => this.setState({
+ item: xhr.response,
+ tail: path.substr(m[0].length)
+ }));
+ prom = prom.catch(() => this.setState({ 'error': 'Cannot load' }));
+ }
+
+ componentDidMount() {
+ this.fetchData();
+ }
+
+ componentWillReceiveProps(nextProps) {
+ this.props = nextProps;
+ this.fetchData();
+ }
+
+ render({}, { item, tail, error }) {
+ if (error)
+ return error;
+
+ if (!item)
+ return 'Loading...';
+
+ return (
+
+
+ { item.name || item.uuid }
+
+ { tail }
+
+
+ );
+ }
+}
+
+export default WBPathDisplay;
diff --git a/frontend/src/js/page/wb-launch-workflow-page.js b/frontend/src/js/page/wb-launch-workflow-page.js
index 60720ed..cda3671 100644
--- a/frontend/src/js/page/wb-launch-workflow-page.js
+++ b/frontend/src/js/page/wb-launch-workflow-page.js
@@ -8,111 +8,11 @@ import WBNameAndUuid from 'wb-name-and-uuid';
import makeArvadosRequest from 'make-arvados-request';
import { wbDisableControls, wbEnableControls } from 'wb-disable-controls';
import linkState from 'linkstate';
-
-function parseDefinition(text) {
- let definition;
- try {
- definition = JSON.parse(text);
- } catch (_) {
- definition = jsyaml.load(text);
- }
- return definition;
-}
-
-function encodeURIComponentIncludingDots(s) {
- return encodeURIComponent(s).replace('.', '%2E');
-}
-
-function inputSpecInfo(inputSpec) {
- const isFile = (inputSpec.type === 'File' || inputSpec.type === 'File[]' ||
- (inputSpec.type.type === 'array' && [].concat(inputSpec.type.items).indexOf('File') !== -1));
-
- const isDirectory = (inputSpec.type === 'Directory' || inputSpec.type === 'Directory[]' ||
- (inputSpec.type.type === 'array' && [].concat(inputSpec.type.items).indexOf('Directory') !== -1));
-
- const isArray = (inputSpec.type === 'File[]' || inputSpec.type === 'Directory[]' ||
- inputSpec.type.type === 'array');
-
- return { isFile, isDirectory, isArray };
-}
-
-function uuidsToCwl(obj) {
- if (obj instanceof Array) {
- const res = [];
- for (let k in obj) {
- res[k] = uuidsToCwl(obj[k]);
- }
- return res;
- }
-
- if (typeof(obj) === 'string' &&
- (/^[0-9a-z]{5}-[0-9a-z]{5}-[0-9a-z]{15}/.exec(obj) ||
- /^[0-9a-f]{32}\+[0-9]+/.exec(obj))) {
-
- const isDirectory = obj.endsWith('/');
-
- return {
- 'class': (isDirectory ? 'Directory' : 'File'),
- 'location': 'keep:' + (isDirectory ? obj.substr(0, obj.length - 1) : obj)
- };
- }
-
- throw Error('Expected Arvados path or array of paths');
-}
-
-function parseKeepRef(value) {
- if (typeof(value) === 'object' && 'location' in value && value.location.startsWith('keep:'))
- return value.location.substr(5);
- return value;
-}
-
-class WBPathDisplay extends Component {
- fetchData() {
- const { app } = this.props;
- const { arvHost, arvToken } = app.state;
- let { path } = this.props;
- if (path.endsWith('/'))
- path = path.substr(0, path.length - 1);
- let m;
- if (m = /^[0-9a-f]{32}\+[0-9]+/.exec(path));
- else if (m = /^[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}/.exec(path));
- else return;
- let prom = makeArvadosRequest(arvHost, arvToken,
- '/arvados/v1/collections/' + m[0]);
- prom = prom.then(xhr => this.setState({
- item: xhr.response,
- tail: path.substr(m[0].length)
- }));
- prom = prom.catch(() => this.setState({ 'error': 'Cannot load' }));
- }
-
- componentDidMount() {
- this.fetchData();
- }
-
- componentWillReceiveProps(nextProps) {
- this.props = nextProps;
- this.fetchData();
- }
-
- render({}, { item, tail, error }) {
- if (error)
- return error;
-
- if (!item)
- return 'Loading...';
-
- return (
-
-
- { item.name || item.uuid }
-
- { tail }
-
-
- );
- }
-}
+import wbParseWorkflowDef from 'wb-parse-workflow-def';
+import wbInputSpecInfo from 'wb-input-spec-info';
+import wbUuidsToCwl from 'wb-uuids-to-cwl';
+import { encodeURIComponentIncludingDots, parseKeepRef } from 'wb-process-misc';
+import WBPathDisplay from 'wb-path-display';
class WBLaunchWorkflowPage extends Component {
constructor(...args) {
@@ -129,7 +29,7 @@ class WBLaunchWorkflowPage extends Component {
let prom = makeArvadosRequest(arvHost, arvToken,
'/arvados/v1/workflows/' + workflowUuid);
prom = prom.then(xhr => {
- const def = parseDefinition(xhr.response.definition);
+ const def = wbParseWorkflowDef(xhr.response.definition);
const inputs = {};
const main = def['$graph'].find(a => (a.id === '#main'));
main.inputs.map(a => (inputs[a.id] = JSON.stringify(a.default)));
@@ -146,7 +46,7 @@ class WBLaunchWorkflowPage extends Component {
renderInput(inputSpec) {
const { app } = this.props;
- const { isFile, isDirectory, isArray } = inputSpecInfo(inputSpec);
+ const { isFile, isDirectory, isArray } = wbInputSpecInfo(inputSpec);
if (!isFile && !isDirectory)
return (
@@ -219,7 +119,7 @@ class WBLaunchWorkflowPage extends Component {
for (let k in this.state.inputs) {
try {
let val = jsyaml.safeLoad(this.state.inputs[k]);
- val = uuidsToCwl(val);
+ val = wbUuidsToCwl(val);
k = k.split('/').slice(1).join('/');
inputs[k] = (val === undefined ? null : val);
} catch (exc) {