mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
[24.0] Do not save workflow on Run without user confirmation
This adds a modal when the user runs a workflow with changes, that asks for user confirmation on whether to proceed without saving changes or to save changes and then proceed. Currently, we _always_ save the workflow when it is run (even if there are no changes at all). Fixes https://github.com/galaxyproject/galaxy/issues/17903
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
@onRefactor="onRefactor"
|
||||
@onShow="hideModal" />
|
||||
<MessagesModal :title="messageTitle" :message="messageBody" :error="messageIsError" @onHidden="resetMessage" />
|
||||
<SaveChangesModal :nav-url.sync="navUrl" :show-modal.sync="showSaveChangesModal" @on-proceed="onNavigate" />
|
||||
<b-modal
|
||||
v-model="showSaveAsModal"
|
||||
title="Save As a New Workflow"
|
||||
@@ -167,7 +168,7 @@
|
||||
<script>
|
||||
import { Toast } from "composables/toast";
|
||||
import { storeToRefs } from "pinia";
|
||||
import Vue, { computed, onUnmounted, ref, unref } from "vue";
|
||||
import Vue, { computed, nextTick, onUnmounted, ref, unref } from "vue";
|
||||
|
||||
import { getUntypedWorkflowParameters } from "@/components/Workflow/Editor/modules/parameters";
|
||||
import { ConfirmDialog } from "@/composables/confirmDialog";
|
||||
@@ -192,6 +193,7 @@ import WorkflowLint from "./Lint.vue";
|
||||
import MessagesModal from "./MessagesModal.vue";
|
||||
import WorkflowOptions from "./Options.vue";
|
||||
import RefactorConfirmationModal from "./RefactorConfirmationModal.vue";
|
||||
import SaveChangesModal from "./SaveChangesModal.vue";
|
||||
import StateUpgradeModal from "./StateUpgradeModal.vue";
|
||||
import WorkflowGraph from "./WorkflowGraph.vue";
|
||||
import MarkdownEditor from "@/components/Markdown/MarkdownEditor.vue";
|
||||
@@ -204,6 +206,7 @@ export default {
|
||||
components: {
|
||||
MarkdownEditor,
|
||||
FlexPanel,
|
||||
SaveChangesModal,
|
||||
StateUpgradeModal,
|
||||
ToolPanel,
|
||||
FormDefault,
|
||||
@@ -337,6 +340,8 @@ export default {
|
||||
showSaveAsModal: false,
|
||||
transform: { x: 0, y: 0, k: 1 },
|
||||
graphOffset: { left: 0, top: 0, width: 0, height: 0 },
|
||||
showSaveChangesModal: false,
|
||||
navUrl: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -677,14 +682,21 @@ export default {
|
||||
const runUrl = `/workflows/run?id=${this.id}`;
|
||||
this.onNavigate(runUrl);
|
||||
},
|
||||
async onNavigate(url) {
|
||||
async onNavigate(url, forceSave = false, ignoreChanges = false) {
|
||||
if (this.isNewTempWorkflow) {
|
||||
await this.onCreate();
|
||||
} else {
|
||||
await this.onSave(true);
|
||||
} else if (this.hasChanges && !forceSave && !ignoreChanges) {
|
||||
// if there are changes, prompt user to save or discard or cancel
|
||||
this.navUrl = url;
|
||||
this.showSaveChangesModal = true;
|
||||
return;
|
||||
} else if (forceSave) {
|
||||
// when forceSave is true, save the workflow before navigating
|
||||
await this.onSave();
|
||||
}
|
||||
|
||||
this.hasChanges = false;
|
||||
await nextTick();
|
||||
this.$router.push(url);
|
||||
},
|
||||
onSave(hideProgress = false) {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<script setup lang="ts">
|
||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { faSave, faTimes, faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { BButton, BModal } from "bootstrap-vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
import localize from "@/utils/localization";
|
||||
|
||||
library.add(faSave, faTimes, faTrash);
|
||||
|
||||
interface Props {
|
||||
/** Show the save changes modal */
|
||||
showModal: boolean;
|
||||
/** The URL to navigate to before saving/ignoring changes */
|
||||
navUrl: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showModal: false,
|
||||
});
|
||||
|
||||
const busy = ref(false);
|
||||
|
||||
const emit = defineEmits<{
|
||||
/** Proceed with or without saving the changes */
|
||||
(e: "on-proceed", url: string, forceSave: boolean, ignoreChanges: boolean): void;
|
||||
/** Update the nav URL prop */
|
||||
(e: "update:nav-url", url: string): void;
|
||||
/** Update the show modal boolean prop */
|
||||
(e: "update:show-modal", showModal: boolean): void;
|
||||
}>();
|
||||
|
||||
const title = localize("You have unsaved changes. Do you want to save them before proceeding?");
|
||||
const body = localize(
|
||||
"Click 'Save' to save your changes and proceed, 'Don't Save' to discard them and proceed, or 'Cancel' to return to the editor."
|
||||
);
|
||||
|
||||
const buttonTitles = {
|
||||
cancel: localize("Do not run proceed and return to editor"),
|
||||
dontSave: localize("Discard changes and proceed"),
|
||||
save: localize("Save changes and proceed"),
|
||||
};
|
||||
|
||||
function closeModal() {
|
||||
emit("update:show-modal", false);
|
||||
emit("update:nav-url", "");
|
||||
}
|
||||
|
||||
function dontSave() {
|
||||
busy.value = true;
|
||||
emit("on-proceed", props.navUrl, false, true);
|
||||
}
|
||||
|
||||
function saveChanges() {
|
||||
busy.value = true;
|
||||
closeModal();
|
||||
emit("on-proceed", props.navUrl, true, false);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BModal :title="title" :visible="props.showModal" @close="closeModal" @hide="closeModal">
|
||||
<div>
|
||||
{{ body }}
|
||||
</div>
|
||||
<template v-slot:modal-footer>
|
||||
<BButton
|
||||
v-b-tooltip.noninteractive.hover
|
||||
:title="buttonTitles['cancel']"
|
||||
variant="secondary"
|
||||
:disabled="busy"
|
||||
@click="closeModal">
|
||||
<FontAwesomeIcon :icon="faTimes" />
|
||||
{{ localize("Cancel") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
v-b-tooltip.noninteractive.hover
|
||||
:title="buttonTitles['dontSave']"
|
||||
variant="danger"
|
||||
:disabled="busy"
|
||||
@click="dontSave">
|
||||
<FontAwesomeIcon :icon="faTrash" />
|
||||
{{ localize("Don't Save") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
v-b-tooltip.noninteractive.hover
|
||||
:title="buttonTitles['save']"
|
||||
variant="primary"
|
||||
:disabled="busy"
|
||||
@click="saveChanges">
|
||||
<FontAwesomeIcon :icon="faSave" />
|
||||
{{ localize("Save") }}
|
||||
</BButton>
|
||||
</template>
|
||||
</BModal>
|
||||
</template>
|
||||
Reference in New Issue
Block a user