Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require name for workflows on save, set default to Unnamed Workflow #17038

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading