From 89fe88a41ba87b9c922f0a17774cc83ca33e12a0 Mon Sep 17 00:00:00 2001 From: Stanislaw Adaszewski Date: Fri, 10 Apr 2020 19:16:09 +0200 Subject: [PATCH] Breaking out some pieces from wb-launch-workflow-page. --- .../js/arvados/process/wb-input-spec-info.js | 14 +++ .../arvados/process/wb-parse-workflow-def.js | 11 ++ .../src/js/arvados/process/wb-process-misc.js | 11 ++ .../src/js/arvados/process/wb-uuids-to-cwl.js | 25 ++++ frontend/src/js/component/wb-path-display.js | 53 ++++++++ .../src/js/page/wb-launch-workflow-page.js | 116 ++---------------- 6 files changed, 122 insertions(+), 108 deletions(-) create mode 100644 frontend/src/js/arvados/process/wb-input-spec-info.js create mode 100644 frontend/src/js/arvados/process/wb-parse-workflow-def.js create mode 100644 frontend/src/js/arvados/process/wb-process-misc.js create mode 100644 frontend/src/js/arvados/process/wb-uuids-to-cwl.js create mode 100644 frontend/src/js/component/wb-path-display.js 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) {