diff --git a/client/src/components/Workflow/Editor/Attributes.vue b/client/src/components/Workflow/Editor/Attributes.vue index 95d36751babc..2247b4dcad41 100644 --- a/client/src/components/Workflow/Editor/Attributes.vue +++ b/client/src/components/Workflow/Editor/Attributes.vue @@ -12,7 +12,7 @@ :state="!nameCurrent ? false : null" @keyup="$emit('update:nameCurrent', nameCurrent)" /> -
+
Version diff --git a/client/src/components/Workflow/Editor/Index.vue b/client/src/components/Workflow/Editor/Index.vue index 09132d88b49d..893b445d06ec 100644 --- a/client/src/components/Workflow/Editor/Index.vue +++ b/client/src/components/Workflow/Editor/Index.vue @@ -18,7 +18,7 @@ title="Save As a New Workflow" ok-title="Save" cancel-title="Cancel" - @ok="doSaveAs"> + @ok="doSaveAs(false)"> @@ -257,14 +257,19 @@ export default { }); const hasChanges = ref(false); + const initialLoading = ref(true); const hasInvalidConnections = computed(() => Object.keys(connectionStore.invalidConnections).length > 0); stepStore.$subscribe((_mutation, _state) => { - hasChanges.value = true; + if (!initialLoading.value) { + hasChanges.value = true; + } }); commentStore.$subscribe((_mutation, _state) => { - hasChanges.value = true; + if (!initialLoading.value) { + hasChanges.value = true; + } }); function resetStores() { @@ -279,8 +284,6 @@ export default { emit("update:confirmation", false); }); - const initialLoading = ref(true); - return { id, connectionStore, @@ -358,18 +361,23 @@ export default { } }, annotation(newAnnotation, oldAnnotation) { - if (newAnnotation != oldAnnotation) { + if (newAnnotation != oldAnnotation && !this.isNewTempWorkflow) { this.hasChanges = true; } }, name(newName, oldName) { - if (newName != oldName) { + if (newName != oldName && !this.isNewTempWorkflow) { this.hasChanges = true; } }, hasChanges() { this.$emit("update:confirmation", this.hasChanges); }, + initialVersion(newVal, oldVal) { + if (newVal != oldVal && oldVal === undefined) { + this.version = this.initialVersion; + } + }, }, async created() { this.lastQueue = new LastQueue(); @@ -524,8 +532,8 @@ export default { window.location = `${getAppRoot()}api/workflows/${this.id}/download?format=json-download`; }, async doSaveAs(create = false) { - const rename_name = this.saveAsName ?? create ? this.name : `SavedAs_${this.name}`; - const rename_annotation = this.saveAsAnnotation ?? create ? this.annotation : ""; + const rename_name = create ? this.name : this.saveAsName ?? `SavedAs_${this.name}`; + const rename_annotation = create ? this.annotation || "" : this.saveAsAnnotation ?? ""; // This is an old web controller endpoint that wants form data posted... const formData = new FormData(); @@ -538,16 +546,7 @@ export default { const response = await axios.post(`${getAppRoot()}workflow/save_workflow_as`, formData); const newId = response.data; - if (create) { - const { addScopePointer } = useScopePointerStore(); - // map scoped stores to existing stores, before updating the id - addScopePointer(newId, this.id); - this.id = newId; - } - - await this.onSave(); - this.hasChanges = false; - this.$router.replace({ query: { id: newId } }); + await this.routeToWorkflow(newId); } catch (e) { this.onWorkflowError("Saving workflow failed, please contact an administrator."); } @@ -575,7 +574,26 @@ export default { const step = { ...this.steps[nodeId], annotation: newAnnotation }; this.onUpdateStep(step); }, - onCreate() { + async routeToWorkflow(id) { + const { addScopePointer, scope } = useScopePointerStore(); + + let pointedTo; + // the current workflow id might be pointing to existing stores + const originalPointed = scope(this.id); + if (originalPointed !== this.id) { + pointedTo = originalPointed; + } else { + pointedTo = this.id; + } + // map scoped stores to existing stores, before updating the id + addScopePointer(id, pointedTo); + + this.id = id; + await this.onSave(); + this.hasChanges = false; + this.$router.replace({ query: { id } }); + }, + async onCreate() { if (!this.name) { const response = "Please provide a name for your workflow."; this.onWorkflowError("Creating workflow failed", response, { @@ -586,8 +604,32 @@ export default { this.onAttributes(); return; } - this.hasChanges = false; - this.doSaveAs(true); + try { + // if nothing other than payload vars changed, just use `create` endpoint + if (!this.hasChanges) { + const payload = { + workflow_name: this.name, + workflow_annotation: this.annotation || "", + workflow_tags: this.tags, + }; + const { data } = await axios.put(`${getAppRoot()}workflow/create`, payload); + const { id } = data; + + await this.routeToWorkflow(id); + } else { + // otherwise, use `save_as` endpoint to include steps, etc. + this.hasChanges = false; + await this.doSaveAs(true); + } + } catch (e) { + this.onWorkflowError("Creating workflow failed"), + e || "Please contact an administrator.", + { + Ok: () => { + this.hideModal(); + }, + }; + } }, onSetData(stepId, newData) { this.lastQueue diff --git a/client/src/components/Workflow/Editor/Options.vue b/client/src/components/Workflow/Editor/Options.vue index 344c51c485bc..1c3f3110e44f 100644 --- a/client/src/components/Workflow/Editor/Options.vue +++ b/client/src/components/Workflow/Editor/Options.vue @@ -84,7 +84,7 @@ async function onSave() { variant="link" aria-label="Save Workflow" class="editor-button-save" - :disabled="!hasChanges" + :disabled="!isNewTempWorkflow && !hasChanges" @click="onSave"> diff --git a/lib/galaxy/webapps/galaxy/controllers/workflow.py b/lib/galaxy/webapps/galaxy/controllers/workflow.py index e839ceedb6c2..ecafcc78c5a5 100644 --- a/lib/galaxy/webapps/galaxy/controllers/workflow.py +++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py @@ -364,6 +364,7 @@ def create(self, trans, payload=None, **kwd): user = trans.get_user() workflow_name = payload.get("workflow_name") workflow_annotation = payload.get("workflow_annotation") + workflow_tags = payload.get("workflow_tags", []) if not workflow_name: return self.message_exception(trans, "Please provide a workflow name.") # Create the new stored workflow @@ -379,6 +380,12 @@ def create(self, trans, payload=None, **kwd): # Add annotation. workflow_annotation = sanitize_html(workflow_annotation) self.add_item_annotation(trans.sa_session, trans.get_user(), stored_workflow, workflow_annotation) + # Add tags + trans.tag_handler.set_tags_from_list( + trans.user, + stored_workflow, + workflow_tags, + ) # Persist session = trans.sa_session session.add(stored_workflow)