8989 <template v-slot :header-buttons >
9090 <ButtonSpinner
9191 id =" execute"
92- title =" Run Tool "
92+ : title =" runButtonTitle "
9393 :disabled =" !canMutateHistory"
9494 class =" btn-sm"
9595 :wait =" showExecuting"
9898 </template >
9999 <template v-slot :buttons >
100100 <ButtonSpinner
101- title =" Run Tool "
101+ : title =" runButtonTitle "
102102 class =" mt-3 mb-3"
103103 :disabled =" !canMutateHistory"
104104 :wait =" showExecuting"
111111
112112<script >
113113import { getGalaxyInstance } from " app" ;
114+ import axios from " axios" ;
114115import ButtonSpinner from " components/Common/ButtonSpinner" ;
115116import Heading from " components/Common/Heading" ;
116117import FormDisplay from " components/Form/FormDisplay" ;
117118import FormElement from " components/Form/FormElement" ;
118119import LoadingSpan from " components/LoadingSpan" ;
119120import ToolEntryPoints from " components/ToolEntryPoints/ToolEntryPoints" ;
121+ import { getAppRoot } from " onload/loadConfig" ;
120122import { mapActions , mapState , storeToRefs } from " pinia" ;
121123import { useHistoryItemsStore } from " stores/historyItemsStore" ;
122124import { useJobStore } from " stores/jobStore" ;
@@ -128,7 +130,8 @@ import { useHistoryStore } from "@/stores/historyStore";
128130import { useUserStore } from " @/stores/userStore" ;
129131
130132import ToolRecommendation from " ../ToolRecommendation" ;
131- import { getToolFormData , submitJob , updateToolFormData } from " ./services" ;
133+ import { getToolFormData , getToolInputs , submitJob , submitToolRequest , updateToolFormData } from " ./services" ;
134+ import { structuredInputs } from " ./structured" ;
132135import ToolCard from " ./ToolCard" ;
133136import { allowCachedJobs } from " ./utilities" ;
134137
@@ -204,6 +207,8 @@ export default {
204207 ],
205208 immutableHistoryMessage:
206209 " This history is immutable and you cannot run tools in it. Please switch to a different history." ,
210+ toolInputs: null ,
211+ submissionStateMessage: null ,
207212 };
208213 },
209214 computed: {
@@ -249,7 +254,15 @@ export default {
249254 return this .currentHistory && canMutateHistory (this .currentHistory );
250255 },
251256 runButtonTitle () {
252- return " Run Tool" ;
257+ if (this .showExecuting ) {
258+ if (this .submissionStateMessage ) {
259+ return this .submissionStateMessage ;
260+ } else {
261+ return " Run Tool" ;
262+ }
263+ } else {
264+ return " Run Tool" ;
265+ }
253266 },
254267 },
255268 watch: {
@@ -301,11 +314,38 @@ export default {
301314 onChangeVersion (newVersion ) {
302315 this .requestTool (newVersion);
303316 },
317+ waitOnRequest (response , requestContent , config , prevRoute ) {
318+ const toolRequestId = response .tool_request_id ;
319+ const handleRequestState = (toolRequestStateResponse ) => {
320+ const state = toolRequestStateResponse .data ;
321+ console .log (` state is ${ state} ` );
322+ if ([" new" ].indexOf (state) !== - 1 ) {
323+ setTimeout (doRequestCheck, 1000 );
324+ } else if (state == " failed" ) {
325+ this .handleError (null , requestContent);
326+ } else {
327+ refreshContentsWrapper ();
328+ this .showForm = false ;
329+ this .showSuccess = true ;
330+ this .handleSubmissionComplete (config, prevRoute);
331+ }
332+ };
333+ const doRequestCheck = () => {
334+ axios
335+ .get (` ${ getAppRoot ()} api/tool_requests/${ toolRequestId} /state` )
336+ .then (handleRequestState)
337+ .catch ((e ) => this .handleError (e, requestContent));
338+ };
339+ setTimeout (doRequestCheck, 1000 );
340+ },
304341 requestTool (newVersion ) {
305342 this .currentVersion = newVersion || this .currentVersion ;
306343 this .disabled = true ;
307344 this .loading = true ;
308345 console .debug (" ToolForm - Requesting tool." , this .id );
346+ getToolInputs (this .id , this .currentVersion ).then ((data ) => {
347+ this .toolInputs = data;
348+ });
309349 return getToolFormData (this .id , this .currentVersion , this .job_id , this .history_id )
310350 .then ((data ) => {
311351 this .formConfig = data;
@@ -331,90 +371,135 @@ export default {
331371 onUpdatePreferredObjectStoreId (preferredObjectStoreId ) {
332372 this .preferredObjectStoreId = preferredObjectStoreId;
333373 },
374+ handleSubmissionComplete (config , prevRoute ) {
375+ const changeRoute = prevRoute === this .$route .fullPath ;
376+ if (changeRoute) {
377+ this .$router .push (` /jobs/submission/success` );
378+ } else {
379+ if ([true , " true" ].includes (config .enable_tool_recommendations )) {
380+ this .showRecommendation = true ;
381+ }
382+ document .querySelector (" .center-panel" ).scrollTop = 0 ;
383+ }
384+ },
385+ handleError (e , errorContent ) {
386+ this .errorMessage = e? .response ? .data ? .err_msg ;
387+ this .showExecuting = false ;
388+ this .submissionStateMessage = null ;
389+ let genericError = true ;
390+ const errorData = e && e .response && e .response .data && e .response .data .err_data ;
391+ if (errorData) {
392+ const errorEntries = Object .entries (errorData);
393+ if (errorEntries .length > 0 ) {
394+ this .validationScrollTo = errorEntries[0 ];
395+ genericError = false ;
396+ }
397+ }
398+ if (genericError) {
399+ this .showError = true ;
400+ this .errorTitle = " Job submission failed." ;
401+ this .errorContent = errorContent;
402+ }
403+ },
334404 onExecute (config , historyId ) {
335405 if (this .validationInternal ) {
336406 this .validationScrollTo = this .validationInternal .slice ();
337407 return ;
338408 }
339409 this .showExecuting = true ;
340- const jobDef = {
341- history_id: historyId,
342- tool_id: this .formConfig .id ,
343- tool_version: this .formConfig .version ,
344- inputs: {
345- ... this .formData ,
346- },
410+ this .submissionStateMessage = " Preparing Request" ;
411+ const inputs = {
412+ ... this .formData ,
347413 };
348- if (this .useEmail ) {
349- jobDef .inputs [" send_email_notification" ] = true ;
350- }
351- if (this .useJobRemapping ) {
352- jobDef .inputs [" rerun_remap_job_id" ] = this .job_id ;
353- }
354- if (this .useCachedJobs ) {
355- jobDef .inputs [" use_cached_job" ] = true ;
414+ const toolId = this .formConfig .id ;
415+ const toolVersion = this .formConfig .version ;
416+ let validatedInputs = null ;
417+ try {
418+ validatedInputs = structuredInputs (inputs, this .toolInputs );
419+ } catch {
420+ // failed validation, just use legacy API
356421 }
357- if (this .preferredObjectStoreId ) {
358- jobDef .preferred_object_store_id = this .preferredObjectStoreId ;
359- }
360- if (this .dataManagerMode === " bundle" ) {
361- jobDef .data_manager_mode = this .dataManagerMode ;
362- }
363- console .debug (" toolForm::onExecute()" , jobDef);
364422 const prevRoute = this .$route .fullPath ;
365- submitJob (jobDef).then (
366- (jobResponse ) => {
367- this .showExecuting = false ;
368- let changeRoute = false ;
369- refreshContentsWrapper ();
370- if (jobResponse .produces_entry_points ) {
371- this .showEntryPoints = true ;
372- this .entryPoints = jobResponse .jobs ;
373- }
374- const nJobs = jobResponse && jobResponse .jobs ? jobResponse .jobs .length : 0 ;
375- if (nJobs > 0 ) {
376- this .showForm = false ;
377- const toolName = this .toolName ;
378- this .saveLatestResponse ({
379- jobDef,
380- jobResponse,
381- toolName,
382- });
383- changeRoute = prevRoute === this .$route .fullPath ;
384- } else {
385- this .showError = true ;
386- this .showForm = true ;
387- this .errorTitle = " Job submission rejected." ;
388- this .errorContent = jobResponse;
423+ if (validatedInputs) {
424+ const toolRequest = {
425+ history_id: historyId,
426+ tool_id: toolId,
427+ tool_version: toolVersion,
428+ inputs: validatedInputs,
429+ };
430+ if (this .useCachedJobs ) {
431+ toolRequest .use_cached_jobs = true ;
432+ }
433+ if (this .preferredObjectStoreId ) {
434+ toolRequest .preferred_object_store_id = this .preferredObjectStoreId ;
435+ }
436+ if (this .dataManagerMode === " bundle" ) {
437+ toolRequest .data_manager_mode = this .dataManagerMode ;
438+ }
439+ this .submissionStateMessage = " Sending Request" ;
440+ submitToolRequest (toolRequest).then (
441+ (jobResponse ) => {
442+ this .submissionStateMessage = " Processing Request" ;
443+ console .log (jobResponse);
444+ this .waitOnRequest (jobResponse, toolRequest, config, prevRoute);
445+ },
446+ (e ) => {
447+ this .handleError (e, toolRequest);
389448 }
390- if (changeRoute) {
391- this .$router .push (` /jobs/submission/success` );
392- } else {
393- if ([true , " true" ].includes (config .enable_tool_recommendations )) {
394- this .showRecommendation = true ;
449+ );
450+ } else {
451+ const jobDef = {
452+ history_id: historyId,
453+ tool_id: toolId,
454+ tool_version: toolVersion,
455+ inputs: inputs,
456+ };
457+ if (this .useEmail ) {
458+ jobDef .inputs [" send_email_notification" ] = true ;
459+ }
460+ if (this .useJobRemapping ) {
461+ jobDef .inputs [" rerun_remap_job_id" ] = this .job_id ;
462+ }
463+ if (this .useCachedJobs ) {
464+ jobDef .inputs [" use_cached_job" ] = true ;
465+ }
466+ if (this .preferredObjectStoreId ) {
467+ jobDef .preferred_object_store_id = this .preferredObjectStoreId ;
468+ }
469+ if (this .dataManagerMode === " bundle" ) {
470+ jobDef .data_manager_mode = this .dataManagerMode ;
471+ }
472+ console .debug (" toolForm::onExecute()" , jobDef);
473+ submitJob (jobDef).then (
474+ (jobResponse ) => {
475+ this .showExecuting = false ;
476+ refreshContentsWrapper ();
477+ if (jobResponse .produces_entry_points ) {
478+ this .showEntryPoints = true ;
479+ this .entryPoints = jobResponse .jobs ;
395480 }
396- document .querySelector (" #center" ).scrollTop = 0 ;
397- }
398- },
399- (e ) => {
400- this .errorMessage = e? .response ? .data ? .err_msg ;
401- this .showExecuting = false ;
402- let genericError = true ;
403- const errorData = e && e .response && e .response .data && e .response .data .err_data ;
404- if (errorData) {
405- const errorEntries = Object .entries (errorData);
406- if (errorEntries .length > 0 ) {
407- this .validationScrollTo = errorEntries[0 ];
408- genericError = false ;
481+ const nJobs = jobResponse && jobResponse .jobs ? jobResponse .jobs .length : 0 ;
482+ if (nJobs > 0 ) {
483+ this .showForm = false ;
484+ const toolName = this .toolName ;
485+ this .saveLatestResponse ({
486+ jobDef,
487+ jobResponse,
488+ toolName,
489+ });
490+ } else {
491+ this .showError = true ;
492+ this .showForm = true ;
493+ this .errorTitle = " Job submission rejected." ;
494+ this .errorContent = jobResponse;
409495 }
496+ this .handleSubmissionComplete (config, prevRoute);
497+ },
498+ (e ) => {
499+ this .handleError (e, jobDef);
410500 }
411- if (genericError) {
412- this .showError = true ;
413- this .errorTitle = " Job submission failed." ;
414- this .errorContent = jobDef;
415- }
416- }
417- );
501+ );
502+ }
418503 },
419504 },
420505};
0 commit comments