import { h, Component, createRef } from 'preact'; import { route } from 'preact-router'; import WBNavbarCommon from 'wb-navbar-common'; import WBArvadosCrumbs from 'wb-arvados-crumbs'; import WBBrowseDialog from 'wb-browse-dialog'; import WBTable from 'wb-table'; import WBNameAndUuid from 'wb-name-and-uuid'; import makeArvadosRequest from 'make-arvados-request'; import { wbDisableControls, wbEnableControls } from 'wb-disable-controls'; import linkState from 'linkstate'; 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) { super(...args); this.browseDialogRef = createRef(); this.state.inputs = {}; this.state.errors = []; } componentDidMount() { let { app, workflowUuid } = this.props; let { arvHost, arvToken } = app.state; let prom = makeArvadosRequest(arvHost, arvToken, '/arvados/v1/workflows/' + workflowUuid); prom = prom.then(xhr => { 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))); this.setState({ 'workflow': xhr.response, 'workflowDefinition': def, 'defaultProcessName': xhr.response.name + ' ' + (new Date().toISOString()), 'defaultProcessDescription': xhr.response.description, inputs }); }); } renderInput(inputSpec) { const { app } = this.props; const { isFile, isDirectory, isArray } = wbInputSpecInfo(inputSpec); if (!isFile && !isDirectory) return (
(this.state.inputs[inputSpec.id] = e.target.value) }>
{ inputSpec.doc }
); const button = ( ); let value = this.state.inputs[inputSpec.id]; if (value) { try { value = jsyaml.load(value); } catch (_) {} } return (
(this.state.inputs[inputSpec.id] = e.target.value) }>
{ button }
{ inputSpec.doc }
{ value ? isArray ? ( ) : ( ) : null }
); } submit() { // first see if all inputs are parseable const inputs = {}; const errors = []; const { workflowDefinition } = this.state; const main = workflowDefinition['$graph'].find(a => (a.id === '#main')); for (let k in this.state.inputs) { try { let val = jsyaml.safeLoad(this.state.inputs[k]); val = wbUuidsToCwl(val); k = k.split('/').slice(1).join('/'); inputs[k] = (val === undefined ? null : val); } catch (exc) { errors.push('Error parsing ' + k + ': ' + exc.message); } } if (errors.length > 0) { this.setState({ errors }); return; } // prepare a request const { app, workflowUuid } = this.props; const { processName, processDescription, defaultProcessName, defaultProcessDescription, projectUuid } = this.state; const { arvHost, arvToken, currentUser } = app.state; const req = { name: processName || defaultProcessName, description: processDescription || defaultProcessDescription, owner_uuid: projectUuid || currentUser.uuid, container_image: 'arvados/jobs', properties: { template_uuid: workflowUuid }, runtime_constraints: { API: true, vcpus: 1, ram: 1073741824 }, cwd: '/var/spool/cwl', command: [ 'arvados-cwl-runner', '--local', '--api=containers', '--project-uuid=' + (projectUuid || currentUser.uuid), '--collection-cache-size=256', '/var/lib/cwl/workflow.json#main', '/var/lib/cwl/cwl.input.json'], output_path: '/var/spool/cwl', priority: 1, state: 'Committed', mounts: { 'stdout': { kind: 'file', path: '/var/spool/cwl/cwl.output.json' }, '/var/spool/cwl': { kind: 'collection', writable: true }, '/var/lib/cwl/workflow.json': { kind: 'json', content: workflowDefinition }, '/var/lib/cwl/cwl.input.json': { kind: 'json', content: inputs } } }; wbDisableControls(); let prom = makeArvadosRequest(arvHost, arvToken, '/arvados/v1/container_requests', { method: 'POST', data: JSON.stringify(req) }); prom = prom.then(xhr => { wbEnableControls(); route('/process/' + xhr.response.uuid); }); // throw Error('Not implemented'); } render({ app, workflowUuid }, { workflow, workflowDefinition, projectUuid, processName, processDescription, defaultProcessName, defaultProcessDescription, errors }) { return (
{ workflow ? (

Launch Workflow

{ projectUuid ? ( ) : null }
(a.id === '#main')).inputs.map(it => [ it.label || it.id, this.renderInput(it) ]) } />
{ errors.length > 0 ? (
{ errors.map(err => ( ))}
) : null }
) :
Loading...
}
); } } export default WBLaunchWorkflowPage;