IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
Browse Source

Finished the new workflow launcher.

pull/1/head
parent
commit
277d8dd293
2 changed files with 150 additions and 9 deletions
  1. +12
    -0
      frontend/src/js/misc/wb-disable-controls.js
  2. +138
    -9
      frontend/src/js/page/wb-launch-workflow-page.js

+ 12
- 0
frontend/src/js/misc/wb-disable-controls.js View File

@@ -0,0 +1,12 @@
function wbDisableControls() {
$('input, select, button').attr('disabled', 'disabled');
$('a').each(function() { $(this).data('old_href', $(this).attr('href')); });
$('a').attr('href', null);
}
function wbEnableControls() {
$('input, select, button').attr('disabled', null);
$('a').each(function() { $(this).attr('href', $(this).data('old_href')); });
}
export { wbEnableControls, wbDisableControls };

+ 138
- 9
frontend/src/js/page/wb-launch-workflow-page.js View File

@@ -1,10 +1,12 @@
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';
function parseDefinition(text) {
@@ -21,6 +23,41 @@ function encodeURIComponentIncludingDots(s) {
return encodeURIComponent(s).replace('.', '%2E');
}
function inputSpecInfo(inputSpec) {
const isFile = (inputSpec.type === 'File' || inputSpec.type === 'File[]' ||
(inputSpec.type.type === 'array' && inputSpec.type.items === 'File'));
const isDirectory = (inputSpec.type === 'Directory' || inputSpec.type === 'Directory[]' ||
(inputSpec.type.type === 'array' && inputSpec.type.items === 'Directory'));
const isArray = (inputSpec.type === 'File[]' || inputSpec.type === 'Directory[]' ||
inputSpec.type.type === 'array');
return { isFile, isDirectory, isArray };
}
function uuidsToCwl(obj, isFile) {
if (obj instanceof Array) {
const res = {};
for (let k in obj) {
res[k] = uuidsToCwl(obj[k], isFile);
}
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))) {
return {
'class': (isFile ? 'File' : 'Directory'),
'location': 'keep:' + obj
};
}
throw Error('Expected Arvados path or array of paths');
}
class WBPathDisplay extends Component {
fetchData() {
const { app, path } = this.props;
@@ -67,6 +104,7 @@ class WBLaunchWorkflowPage extends Component {
super(...args);
this.browseDialogRef = createRef();
this.state.inputs = {};
this.state.errors = [];
}
componentDidMount() {
@@ -86,14 +124,7 @@ class WBLaunchWorkflowPage extends Component {
renderInput(inputSpec) {
const { app } = this.props;
const isFile = (inputSpec.type === 'File' || inputSpec.type === 'File[]' ||
(inputSpec.type.type === 'array' && inputSpec.type.items === 'File'));
const isDirectory = (inputSpec.type === 'Directory' || inputSpec.type === 'Directory[]' ||
(inputSpec.type.type === 'array' && inputSpec.type.items === 'Directory'));
const isArray = true; // (inputSpec.type === 'File[]' || inputSpec.type === 'Directory[]' ||
// inputSpec.type.type === 'array');
const { isFile, isDirectory, isArray } = inputSpecInfo(inputSpec);
if (!isFile && !isDirectory)
return (
@@ -153,9 +184,97 @@ class WBLaunchWorkflowPage extends Component {
);
}
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]);
const { isFile } = inputSpecInfo(main.inputs.find(a => (a.id === k)));
val = uuidsToCwl(val, isFile);
k = k.split('/').slice(1).join('/');
inputs[k] = 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 }) {
defaultProcessName, defaultProcessDescription, errors }) {
return (
<div>
@@ -221,6 +340,16 @@ class WBLaunchWorkflowPage extends Component {
Submit
</button>
</div>
{ errors.length > 0 ? (
<div class="form-group">
{ errors.map(err => (
<div class="alert alert-danger" role="alert">
{ err }
</div>
))}
</div>
) : null }
</form>) : <div>Loading...</div> }
</div>
);


Loading…
Cancel
Save