diff --git a/client/galaxy/scripts/components/WaitButton.vue b/client/galaxy/scripts/components/WaitButton.vue new file mode 100644 index 00000000000..884c01bd52d --- /dev/null +++ b/client/galaxy/scripts/components/WaitButton.vue @@ -0,0 +1,67 @@ +/** Button variant with waiting and progress tracking. */ + + + diff --git a/client/galaxy/scripts/components/Workflow/Run/WorkflowRun.vue b/client/galaxy/scripts/components/Workflow/Run/WorkflowRun.vue new file mode 100644 index 00000000000..be0c65ed819 --- /dev/null +++ b/client/galaxy/scripts/components/Workflow/Run/WorkflowRun.vue @@ -0,0 +1,115 @@ + + + diff --git a/client/galaxy/scripts/components/Workflow/Run/WorkflowRunSuccess.vue b/client/galaxy/scripts/components/Workflow/Run/WorkflowRunSuccess.vue new file mode 100644 index 00000000000..1e6426db430 --- /dev/null +++ b/client/galaxy/scripts/components/Workflow/Run/WorkflowRunSuccess.vue @@ -0,0 +1,106 @@ + + + diff --git a/client/galaxy/scripts/entry/analysis/AnalysisRouter.js b/client/galaxy/scripts/entry/analysis/AnalysisRouter.js index 7cec09f614d..b110e99c372 100644 --- a/client/galaxy/scripts/entry/analysis/AnalysisRouter.js +++ b/client/galaxy/scripts/entry/analysis/AnalysisRouter.js @@ -31,13 +31,11 @@ import WorkflowList from "components/Workflow/WorkflowList.vue"; import HistoryImport from "components/HistoryImport.vue"; import HistoryView from "components/HistoryView.vue"; import WorkflowInvocationReport from "components/WorkflowInvocationReport.vue"; +import WorkflowRun from "components/Workflow/Run/WorkflowRun.vue"; import RecentInvocations from "components/User/RecentInvocations.vue"; import HistoryList from "mvc/history/history-list"; import PluginList from "components/PluginList.vue"; -import ToolFormComposite from "mvc/tool/tool-form-composite"; import QueryStringParsing from "utils/query-string-parsing"; -import Utils from "utils/utils"; -import Ui from "mvc/ui/ui-misc"; import DatasetError from "mvc/dataset/dataset-error"; import DatasetEditAttributes from "mvc/dataset/dataset-edit-attributes"; import Citations from "components/Citations.vue"; @@ -94,9 +92,12 @@ export const getAnalysisRouter = Galaxy => return (Galaxy.user && Galaxy.user.id) || this.require_login.indexOf(name) == -1; }, - _display_vue_helper: function(component, propsData = {}) { + _display_vue_helper: function(component, propsData = {}, active_tab = null) { const instance = Vue.extend(component); const container = document.createElement("div"); + if (active_tab) { + container.active_tab = active_tab; + } this.page.display(container); new instance({ store, propsData }).$mount(container); }, @@ -406,21 +407,7 @@ export const getAnalysisRouter = Galaxy => /** load workflow by its url in run mode */ _loadWorkflow: function() { - Utils.get({ - url: `${getAppRoot()}api/workflows/${Utils.getQueryString("id")}/download?style=run`, - success: response => { - this.page.display(new ToolFormComposite.View(_.extend(response, { active_tab: "workflow" }))); - }, - error: response => { - const error_msg = response.err_msg || "Error occurred while loading the resource."; - const options = { - message: error_msg, - status: "danger", - persistent: true, - active_tab: "workflow" - }; - this.page.display(new Ui.Message(options)); - } - }); + const workflowId = QueryStringParsing.get("id"); + this._display_vue_helper(WorkflowRun, { workflowId: workflowId }, "workflow"); } }); diff --git a/client/galaxy/scripts/mvc/tool/tool-form-composite.js b/client/galaxy/scripts/mvc/tool/tool-form-composite.js index f1f97d78a79..09c093b51f9 100644 --- a/client/galaxy/scripts/mvc/tool/tool-form-composite.js +++ b/client/galaxy/scripts/mvc/tool/tool-form-composite.js @@ -7,14 +7,11 @@ import { getGalaxyInstance } from "app"; import _l from "utils/localization"; import Utils from "utils/utils"; import Deferred from "utils/deferred"; -import Ui from "mvc/ui/ui-misc"; import Form from "mvc/form/form-view"; import FormData from "mvc/form/form-data"; import ToolFormBase from "mvc/tool/tool-form-base"; import Modal from "mvc/ui/ui-modal"; -import Webhooks from "mvc/webhooks"; import WorkflowIcons from "mvc/workflow/workflow-icons"; -import { mountWorkflowInvocationState } from "components/WorkflowInvocationState"; var View = Backbone.View.extend({ initialize: function(options) { @@ -25,14 +22,9 @@ var View = Backbone.View.extend({ if (options && options.active_tab) { this.active_tab = options.active_tab; } - this.setElement( - $("
") - .addClass("ui-form-composite") - .append((this.$message = $("
").addClass("mb-4"))) - .append((this.$header = $("
"))) - .append((this.$steps = $("
"))) - ); - $("body").append(this.$el); + this.setRunButtonStatus = options.setRunButtonStatus; + this.handleInvocations = options.handleInvocations; + this.setElement(options.el); this._configure(); this.render(); }, @@ -208,8 +200,6 @@ var View = Backbone.View.extend({ render: function() { var self = this; this.deferred.reset(); - this._renderHeader(); - this._renderMessage(); this._renderParameters(); this._renderHistory(); this._renderUseCachedJob(); @@ -219,53 +209,6 @@ var View = Backbone.View.extend({ }); }, - /** Render header */ - _renderHeader: function() { - var self = this; - this.execute_btn = new Ui.Button({ - id: "run-workflow", - icon: "fa-check", - title: _l("Run workflow"), - cls: "btn btn-primary", - onclick: function() { - self._execute(); - } - }); - this.$header - .addClass("h4") - .empty() - .append(`Workflow: ${this.model.get("name")}`) - .append(this.execute_btn.$el); - }, - - /** Render message */ - _renderMessage: function() { - this.$message.empty(); - if (this.model.get("has_upgrade_messages")) { - this.$message.append( - new Ui.Message({ - message: - "Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.", - status: "warning", - persistent: true, - fade: false - }).$el - ); - } - var step_version_changes = this.model.get("step_version_changes"); - if (step_version_changes && step_version_changes.length > 0) { - this.$message.append( - new Ui.Message({ - message: - "Some tools are being executed with different versions compared to those available when this workflow was last saved because the other versions are not or no longer available on this Galaxy instance. To upgrade your workflow and dismiss this message simply edit the workflow and re-save it.", - status: "warning", - persistent: true, - fade: false - }).$el - ); - } - }, - /** Render workflow parameters */ _renderParameters: function() { var self = this; @@ -283,7 +226,7 @@ var View = Backbone.View.extend({ }); } }); - this._append(this.$steps.empty(), this.wp_form.$el); + this._append(this.$el.empty(), this.wp_form.$el); } }, @@ -319,7 +262,7 @@ var View = Backbone.View.extend({ } ] }); - this._append(this.$steps, this.history_form.$el); + this._append(this.$el, this.history_form.$el); }, /** Render Workflow Options */ @@ -331,7 +274,7 @@ var View = Backbone.View.extend({ title: "Workflow Resource Options", inputs: this.model.get("workflow_resource_parameters") }); - this._append(this.$steps, this.workflow_resource_parameters_form.$el); + this._append(this.$el, this.workflow_resource_parameters_form.$el); } }, @@ -365,7 +308,7 @@ var View = Backbone.View.extend({ } ] }); - this._append(this.$steps, this.job_options_form.$el); + this._append(this.$el, this.job_options_form.$el); } }, @@ -375,7 +318,7 @@ var View = Backbone.View.extend({ var self = this; var form = null; this.deferred.execute(promise => { - self.$steps.addClass("ui-steps"); + self.$el.addClass("ui-steps"); if (step.step_type == "tool") { step.postchange = function(process, form) { var current_state = { @@ -458,17 +401,14 @@ var View = Backbone.View.extend({ } } self.forms[step.index] = form; - self._append(self.$steps, form.$el); + self._append(self.$el, form.$el); if (step.needs_refresh) { self._refreshStep(step); } form.portlet[!self.show_progress ? "enable" : "disable"](); if (self.show_progress) { - self.execute_btn.model.set({ - wait: true, - wait_text: "Preparing...", - percentage: ((step.index + 1) * 100.0) / self.steps.length - }); + const percentage = ((step.index + 1) * 100.0) / self.steps.length; + this.setRunButtonStatus(false, "Preparing...", percentage); } Galaxy.emit.debug("tool-form-composite::initialize()", `${step.index} : Workflow step state ready.`, step); window.setTimeout(() => { @@ -528,34 +468,14 @@ var View = Backbone.View.extend({ } }, - /** Refresh the history after job submission while form is shown */ - _refreshHistory: function() { - const Galaxy = getGalaxyInstance(); - var self = this; - var history = Galaxy && Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.model; - if (this._refresh_history) { - window.clearTimeout(this._refresh_history); - } - if (history) { - history.refresh().success(() => { - if (history.numOfUnfinishedShownContents() === 0) { - self._refresh_history = window.setTimeout(() => { - self._refreshHistory(); - }, history.UPDATE_DELAY); - } - }); - } - }, - /** Build remaining steps */ - _execute: function() { - var self = this; + execute: function() { this.show_progress = true; this._enabled(false); this.deferred.execute(promise => { window.setTimeout(() => { promise.resolve(); - self._submit(); + this._submit(); }, 0); }); }, @@ -628,22 +548,13 @@ var View = Backbone.View.extend({ type: "POST", url: `${getAppRoot()}api/workflows/${this.model.id}/invocations`, data: job_def, - success: function(response) { + success: response => { Galaxy.emit.debug("tool-form-composite::submit", "Submission successful.", response); - self.$el.children().hide(); - self.$el.append(self._templateSuccess(response)); - mountWorkflowInvocationState(); - // Show Webhook if job is running if ($.isArray(response) && response.length > 0) { - self.$el.append($("
", { id: "webhook-view" })); - new Webhooks.WebhookView({ - type: "workflow", - toolId: job_def.tool_id, - toolVersion: job_def.tool_version - }); + this.handleInvocations(response); + } else { + this.submissionErrorModal(job_def, response); } - - self._refreshHistory(); }, error: function(response) { Galaxy.emit.debug("tool-form-composite::submit", "Submission failed.", response); @@ -663,15 +574,7 @@ var View = Backbone.View.extend({ } } if (!input_found) { - self.modal.show({ - title: _l("Workflow submission failed"), - body: self._templateError(job_def, response && response.err_msg), - buttons: { - Close: function() { - self.modal.hide(); - } - } - }); + this.submissionErrorModal(job_def, response); } }, complete: function() { @@ -688,11 +591,7 @@ var View = Backbone.View.extend({ /** Set enabled/disabled state */ _enabled: function(enabled) { - this.execute_btn.model.set({ - wait: !enabled, - wait_text: "Sending...", - percentage: -1 - }); + this.setRunButtonStatus(enabled, "Sending...", -1); if (this.wp_form) { this.wp_form.portlet[enabled ? "enable" : "disable"](); } @@ -718,52 +617,19 @@ var View = Backbone.View.extend({ return true; }, - /** Templates */ - _templateSuccess: function(response) { - const Galaxy = getGalaxyInstance(); - if ($.isArray(response) && response.length > 0) { - let timesExecuted = ""; - // Default destination blurb, used for a single execution, same history. - let destinationBlurb = - "You can check the status of queued jobs and view the resulting data by refreshing the History pane, if this has not already happened automatically."; - const newHistoryTarget = - (response[0].history_id && - Galaxy.currHistoryPanel && - Galaxy.currHistoryPanel.model.id != response[0].history_id) || - false; - if (response.length > 1) { - // Executed more than one time, build blurb but skip history link. - timesExecuted = ` - ${response.length} times`; - if (newHistoryTarget) { - destinationBlurb = `This workflow will generate results in multiple histories. You can observe progress in the history multi-view.`; + submissionErrorModal: function(job_def, response) { + this.modal.show({ + title: _l("Workflow submission failed"), + body: this._templateError(job_def, response && response.err_msg), + buttons: { + Close: () => { + this.modal.hide(); } - } else if (newHistoryTarget) { - // Single execution, with a destination other than the - // current history. Present a link. - destinationBlurb = `This workflow will generate results in a new history. Switch to that history now.`; } - let success = ` -
-
-

- Successfully invoked workflow ${Utils.sanitize(this.model.get("name"))}${timesExecuted}. -

-

- ${destinationBlurb} -

-
`; - for (const invocation of response) { - success += `
`; - } - success += "
"; - return $(success); - } else { - return this._templateError(response, "Invalid success response. No invocations found."); - } + }); }, + /** Templates */ _templateError: function(response, err_msg) { return $("
") .addClass("errormessagelarge")