Skip to content

Commit

Permalink
Merge pull request galaxyproject#17038 from ahmedhamidawan/workflow_e…
Browse files Browse the repository at this point in the history
…ditor_require_name

Require name for workflows on save, set default to Unnamed Workflow
  • Loading branch information
martenson authored Nov 17, 2023
2 parents fc01188 + 3da9c41 commit 8806d60
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 11 deletions.
30 changes: 20 additions & 10 deletions client/src/components/Workflow/Editor/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@

<script>
import axios from "axios";
import { Toast } from "composables/toast";
import { storeToRefs } from "pinia";
import Vue, { computed, onUnmounted, ref, unref } from "vue";
Expand Down Expand Up @@ -315,7 +316,7 @@ export default {
license: null,
creator: null,
annotation: null,
name: null,
name: "Unnamed Workflow",
tags: this.workflowTags,
stateMessages: [],
insertedStateMessages: [],
Expand Down Expand Up @@ -591,14 +592,7 @@ export default {
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, {
Ok: () => {
this.hideModal();
},
});
this.onAttributes();
if (!this.nameValidate()) {
return;
}
try {
Expand All @@ -610,12 +604,17 @@ export default {
workflow_tags: this.tags,
};
const { data } = await axios.put(`${getAppRoot()}workflow/create`, payload);
const { id } = data;
const { id, message } = data;
await this.routeToWorkflow(id);
Toast.success(message);
} else {
// otherwise, use `save_as` endpoint to include steps, etc.
await this.doSaveAs(true);
const stepCount = Object.keys(this.steps).length;
Toast.success(
`Created workflow ${this.name} with ${stepCount} ${stepCount === 1 ? "step" : "steps"}.`
);
}
} catch (e) {
this.onWorkflowError("Creating workflow failed"),
Expand All @@ -627,6 +626,14 @@ export default {
};
}
},
nameValidate() {
if (!this.name) {
Toast.error("Please provide a name for your workflow.");
this.onAttributes();
return false;
}
return true;
},
onSetData(stepId, newData) {
this.lastQueue
.enqueue(() => getModule(newData, stepId, this.stateStore.setLoadingState))
Expand Down Expand Up @@ -688,6 +695,9 @@ export default {
});
},
onSave(hideProgress = false) {
if (!this.nameValidate()) {
return;
}
!hideProgress && this.onWorkflowMessage("Saving workflow...", "progress");
return saveWorkflow(this)
.then((data) => {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Workflow/Editor/Options.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ async function onSave() {
@click="$emit('onAttributes')">
<span class="fa fa-pencil-alt" />
</BButton>
<b-button-group v-b-tooltip class="editor-button-save-group" :title="saveHover">
<b-button-group v-b-tooltip.hover.noninteractive class="editor-button-save-group" :title="saveHover">
<BButton
id="workflow-save-button"
role="button"
Expand Down
2 changes: 2 additions & 0 deletions lib/galaxy/managers/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,8 @@ def update_workflow_from_raw_description(
update_dict = raw_workflow_description.as_dict
if "name" in update_dict:
sanitized_name = sanitize_html(update_dict["name"])
if not sanitized_name:
raise exceptions.RequestParameterInvalidException("Workflow must have a valid name")
workflow.name = sanitized_name
stored_workflow.name = sanitized_name
if update_dict.get("annotation") is not None:
Expand Down
2 changes: 2 additions & 0 deletions lib/galaxy/webapps/galaxy/api/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,8 @@ def update(self, trans: GalaxyWebTransaction, id, payload, **kwds):
steps_updated = "steps" in workflow_dict
if name_updated and not steps_updated:
sanitized_name = sanitize_html(new_workflow_name or old_workflow.name)
if not sanitized_name:
raise exceptions.MessageException("Workflow must have a valid name.")
workflow = old_workflow.copy(user=trans.user)
workflow.stored_workflow = stored_workflow
workflow.name = sanitized_name
Expand Down
18 changes: 18 additions & 0 deletions lib/galaxy_test/api/test_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,24 @@ def test_update_name(self):
workflow_dict = self.workflow_populator.download_workflow(workflow_id)
assert workflow_dict["license"] == "AAL"

def test_update_name_empty(self):
# Update doesn't allow empty names.

# Load a workflow with a given name.
original_name = "test update name"
workflow_object = self.workflow_populator.load_workflow(name=original_name)
upload_response = self.__test_upload(workflow=workflow_object, name=original_name)
workflow = upload_response.json()
assert workflow["name"] == original_name

# Try to update the name to an empty string (also change steps to force an update).
data = {"name": "", "steps": {}}
update_response = self._update_workflow(workflow["id"], data)
assert update_response.json()["err_msg"] == "Workflow must have a valid name"
self._assert_status_code_is(update_response, 400)
workflow_dict = self.workflow_populator.download_workflow(workflow["id"])
assert workflow_dict["name"] == original_name

def test_refactor(self):
workflow_id = self.workflow_populator.upload_yaml_workflow(
"""
Expand Down

0 comments on commit 8806d60

Please sign in to comment.