Merge pull request #15752 from Budibase/BUDI-9127/modal-to-prevent-losing-rest-datasource-changes

Modal to prevent losing REST datasource changes
This commit is contained in:
Adria Navarro 2025-03-18 12:34:00 +01:00 committed by GitHub
commit 2e225094ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 98 additions and 14 deletions

View File

@ -1,16 +1,18 @@
<script>
<script lang="ts">
import { Modal, ModalContent, Body } from "@budibase/bbui"
export let title = ""
export let body = ""
export let okText = "Confirm"
export let cancelText = "Cancel"
export let onOk = undefined
export let onCancel = undefined
export let warning = true
export let disabled = false
export let title: string = ""
export let body: string = ""
export let okText: string = "Confirm"
export let cancelText: string = "Cancel"
export let size: "S" | "M" | "L" | "XL" | undefined = undefined
export let onOk: (() => void) | undefined = undefined
export let onCancel: (() => void) | undefined = undefined
export let onClose: (() => void) | undefined = undefined
export let warning: boolean = true
export let disabled: boolean = false
let modal
let modal: Modal
export const show = () => {
modal.show()
@ -20,14 +22,16 @@
}
</script>
<Modal bind:this={modal} on:hide={onCancel}>
<Modal bind:this={modal} on:hide={onClose ?? onCancel}>
<ModalContent
onConfirm={onOk}
{onCancel}
{title}
confirmText={okText}
{cancelText}
{warning}
{disabled}
{size}
>
<Body size="S">
{body}

View File

@ -1,5 +1,5 @@
<script>
import { goto, params } from "@roxi/routify"
import { beforeUrlChange, goto, params } from "@roxi/routify"
import { datasources, flags, integrations, queries } from "@/stores/builder"
import { environment } from "@/stores/portal"
import {
@ -25,7 +25,7 @@
EditorModes,
} from "@/components/common/CodeMirrorEditor.svelte"
import RestBodyInput from "./RestBodyInput.svelte"
import { capitalise } from "@/helpers"
import { capitalise, confirm } from "@/helpers"
import { onMount } from "svelte"
import restUtils from "@/helpers/data/utils"
import {
@ -63,6 +63,7 @@
let nestedSchemaFields = {}
let saving
let queryNameLabel
let mounted = false
$: staticVariables = datasource?.config?.staticVariables || {}
@ -104,8 +105,10 @@
$: runtimeUrlQueries = readableToRuntimeMap(mergedBindings, breakQs)
$: originalQuery = originalQuery ?? cloneDeep(query)
$: builtQuery = buildQuery(query, runtimeUrlQueries, requestBindings)
$: originalQuery = mounted
? originalQuery ?? cloneDeep(builtQuery)
: undefined
$: isModified = JSON.stringify(originalQuery) !== JSON.stringify(builtQuery)
function getSelectedQuery() {
@ -208,11 +211,14 @@
originalQuery = null
queryNameLabel.disableEditingState()
return { ok: true }
} catch (err) {
notifications.error(`Error saving query`)
} finally {
saving = false
}
return { ok: false }
}
const validateQuery = async () => {
@ -474,6 +480,38 @@
staticVariables,
restBindings
)
mounted = true
})
$beforeUrlChange(async () => {
if (!isModified) {
return true
}
return await confirm({
title: "Some updates are not saved",
body: "Some of your changes are not yet saved. Do you want to save them before leaving?",
okText: "Save and continue",
cancelText: "Discard and continue",
size: "M",
onConfirm: async () => {
const saveResult = await saveQuery()
if (!saveResult.ok) {
// We can't leave as the query was not properly saved
return false
}
return true
},
onCancel: () => {
// Leave without saving anything
return true
},
onClose: () => {
return false
},
})
})
</script>

View File

@ -0,0 +1,41 @@
import ConfirmDialog from "@/components/common/ConfirmDialog.svelte"
export enum ConfirmOutput {}
export async function confirm(props: {
title: string
body?: string
okText?: string
cancelText?: string
size?: "S" | "M" | "L" | "XL"
onConfirm?: () => void
onCancel?: () => void
onClose?: () => void
}) {
return await new Promise(resolve => {
const dialog = new ConfirmDialog({
target: document.body,
props: {
title: props.title,
body: props.body,
okText: props.okText,
cancelText: props.cancelText,
size: props.size,
warning: false,
onOk: () => {
dialog.$destroy()
resolve(props.onConfirm?.() || true)
},
onCancel: () => {
dialog.$destroy()
resolve(props.onCancel?.() || false)
},
onClose: () => {
dialog.$destroy()
resolve(props.onClose?.() || false)
},
},
})
dialog.show()
})
}

View File

@ -11,3 +11,4 @@ export {
} from "./helpers"
export * as featureFlag from "./featureFlags"
export * as bindings from "./bindings"
export * from "./confirm"