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!
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

154 рядки
5.5KB

  1. import { h, Component, createRef } from 'preact';
  2. import WBNavbarCommon from 'wb-navbar-common';
  3. import WBArvadosCrumbs from 'wb-arvados-crumbs';
  4. import WBBrowseDialog from 'wb-browse-dialog';
  5. import WBTable from 'wb-table';
  6. import makeArvadosRequest from 'make-arvados-request';
  7. import linkState from 'linkstate';
  8. function parseDefinition(text) {
  9. let definition;
  10. try {
  11. definition = JSON.parse(text);
  12. } catch (_) {
  13. definition = jsyaml.load(text);
  14. }
  15. return definition;
  16. }
  17. class WBLaunchWorkflowPage extends Component {
  18. constructor(...args) {
  19. super(...args);
  20. this.browseDialogRef = createRef();
  21. this.state.inputs = {};
  22. }
  23. componentDidMount() {
  24. let { app, workflowUuid } = this.props;
  25. let { arvHost, arvToken } = app.state;
  26. let prom = makeArvadosRequest(arvHost, arvToken,
  27. '/arvados/v1/workflows/' + workflowUuid);
  28. prom = prom.then(xhr => this.setState({
  29. 'workflow': xhr.response,
  30. 'workflowDefinition': parseDefinition(xhr.response.definition),
  31. 'defaultProcessName': xhr.response.name + ' ' + (new Date().toISOString()),
  32. 'defaultProcessDescription': xhr.response.description
  33. }));
  34. }
  35. renderInput(inputSpec) {
  36. const isFile = (inputSpec.type === 'File' || inputSpec.type === 'File[]' ||
  37. (inputSpec.type.type === 'array' && inputSpec.type.items === 'File'));
  38. const isDirectory = (inputSpec.type === 'Directory' || inputSpec.type === 'Directory[]' ||
  39. (inputSpec.type.type === 'array' && inputSpec.type.items === 'Directory'));
  40. const isArray = (inputSpec.type === 'File[]' || inputSpec.type === 'Directory[]' ||
  41. inputSpec.type.type === 'array');
  42. if (!isFile && !isDirectory)
  43. return (
  44. <input class="form-control w-100" type="text" placeholder={ inputSpec.doc }
  45. value={ this.state.inputs[inputSpec.id] }
  46. onchange={ e => (this.state.inputs[inputSpec.id] = e.target.value) }></input>
  47. );
  48. const button = (
  49. <button class="btn btn-outline-primary"
  50. onclick={ e => {
  51. e.preventDefault();
  52. this.browseDialogRef.current.show(isFile ? 'file' : 'directory', isArray,
  53. v => {
  54. this.state.inputs[inputSpec.id] = v.toString();
  55. this.setState({});
  56. });
  57. } }>
  58. Browse...
  59. </button>
  60. );
  61. return (
  62. <div class="input-group">
  63. <input class="form-control w-100" type="text" placeholder={ inputSpec.doc }
  64. value={ this.state.inputs[inputSpec.id] }
  65. onchange={ e => (this.state.inputs[inputSpec.id] = e.target.value) }></input>
  66. <div class="input-group-append">
  67. { button }
  68. </div>
  69. </div>
  70. );
  71. }
  72. render({ app, workflowUuid },
  73. { workflow, workflowDefinition, projectUuid, processName, processDescription,
  74. defaultProcessName, defaultProcessDescription }) {
  75. return (
  76. <div>
  77. <WBNavbarCommon app={ app } />
  78. <WBBrowseDialog app={ app } ref={ this.browseDialogRef } />
  79. { workflow ?
  80. (<form class="container-fluid">
  81. <h1>Launch Workflow</h1>
  82. <div class="form-group">
  83. <label>Workflow</label>
  84. <WBArvadosCrumbs app={ app } uuid={ workflowUuid } />
  85. </div>
  86. <div class="form-group">
  87. <label for="projectUuid">Project UUID</label>
  88. <div>
  89. { projectUuid ? (
  90. <WBArvadosCrumbs app={ app } uuid={ projectUuid } />
  91. ) : null }
  92. <div class="input-group mb-3">
  93. <input type="text" class="form-control" id="projectUuid"
  94. placeholder="Enter Project UUID" aria-label="Project UUID"
  95. aria-describedby="button-addon2" value={ projectUuid }
  96. onChange={ linkState(this, 'projectUuid') } />
  97. <div class="input-group-append">
  98. <button class="btn btn-primary" type="button"
  99. id="button-addon2" onclick={ e => { e.preventDefault();
  100. this.browseDialogRef.current.show('owner', false,
  101. projectUuid => this.setState({ projectUuid })); } }>Browse</button>
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. <div class="form-group">
  107. <label for="processName">Process Name</label>
  108. <input type="text" class="form-control" id="processName"
  109. placeholder={ defaultProcessName } value={ processName }
  110. onChange={ linkState(this, 'processName') }/>
  111. </div>
  112. <div class="form-group">
  113. <label for="processDescription">Process Description</label>
  114. <input type="text" class="form-control" id="processDescription"
  115. placeholder={ defaultProcessDescription } value={ processDescription }
  116. onChange={ linkState(this, 'processDescription') } />
  117. </div>
  118. <div class="form-group">
  119. <label for="inputs">Inputs</label>
  120. <WBTable columns={ [ 'Name', 'Value'] }
  121. rows={ workflowDefinition.$graph.find(a => (a.id === '#main')).inputs.map(it => [
  122. it.label || it.id,
  123. this.renderInput(it)
  124. ]) } />
  125. </div>
  126. </form>) : <div>Loading...</div> }
  127. </div>
  128. );
  129. }
  130. }
  131. export default WBLaunchWorkflowPage;