+
diff --git a/packages/bbui/src/Modal/ModalContent.svelte b/packages/bbui/src/Modal/ModalContent.svelte
index 16338b1ed2..dae9b9e8af 100644
--- a/packages/bbui/src/Modal/ModalContent.svelte
+++ b/packages/bbui/src/Modal/ModalContent.svelte
@@ -16,7 +16,7 @@
export let onConfirm = undefined
export let disabled = false
- const { hide } = getContext(Context.Modal)
+ const { hide, cancel } = getContext(Context.Modal)
let loading = false
$: confirmDisabled = disabled || loading
@@ -56,7 +56,7 @@
>
{#if showCancelButton}
-
+
{/if}
{#if showConfirmButton}
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/TriggerAutomation.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/TriggerAutomation.svelte
index e40c182131..545a805cc5 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/TriggerAutomation.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/TriggerAutomation.svelte
@@ -1,5 +1,5 @@
+
+{#if $confirmationStore.showConfirmation}
+
+
+ {$confirmationStore.text}
+
+
+{/if}
diff --git a/packages/client/src/store/auth.js b/packages/client/src/store/auth.js
index 9e01a5648f..9829d2e350 100644
--- a/packages/client/src/store/auth.js
+++ b/packages/client/src/store/auth.js
@@ -1,40 +1,11 @@
import * as API from "../api"
import { writable, get } from "svelte/store"
-import { initialise } from "./initialise"
-import { routeStore } from "./routes"
import { builderStore } from "./builder"
import { TableNames } from "../constants"
const createAuthStore = () => {
const store = writable(null)
- const goToDefaultRoute = () => {
- // Setting the active route forces an update of the active screen ID,
- // even if we're on the same URL
- routeStore.actions.setActiveRoute("/")
-
- // Navigating updates the URL to reflect this route
- routeStore.actions.navigate("/")
- }
-
- // Logs a user in
- const logIn = async ({ email, password }) => {
- const auth = await API.logIn({ email, password })
- if (auth.success) {
- await fetchUser()
- await initialise()
- goToDefaultRoute()
- }
- }
-
- // Logs a user out
- const logOut = async () => {
- store.set(null)
- window.document.cookie = `budibase:auth=; budibase:currentapp=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`
- await initialise()
- goToDefaultRoute()
- }
-
// Fetches the user object if someone is logged in and has reloaded the page
const fetchUser = async () => {
// Fetch the first user if inside the builder
@@ -54,7 +25,7 @@ const createAuthStore = () => {
return {
subscribe: store.subscribe,
- actions: { logIn, logOut, fetchUser },
+ actions: { fetchUser },
}
}
diff --git a/packages/client/src/store/confirmation.js b/packages/client/src/store/confirmation.js
new file mode 100644
index 0000000000..497b021b04
--- /dev/null
+++ b/packages/client/src/store/confirmation.js
@@ -0,0 +1,39 @@
+import { writable, get } from "svelte/store"
+
+const initialState = {
+ showConfirmation: false,
+ title: null,
+ text: null,
+ callback: null,
+}
+
+const createConfirmationStore = () => {
+ const store = writable(initialState)
+
+ const showConfirmation = (title, text, callback) => {
+ store.set({
+ showConfirmation: true,
+ title,
+ text,
+ callback,
+ })
+ }
+ const confirm = async () => {
+ const state = get(store)
+ if (!state.showConfirmation || !state.callback) {
+ return
+ }
+ store.set(initialState)
+ await state.callback()
+ }
+ const cancel = () => {
+ store.set(initialState)
+ }
+
+ return {
+ subscribe: store.subscribe,
+ actions: { showConfirmation, confirm, cancel },
+ }
+}
+
+export const confirmationStore = createConfirmationStore()
diff --git a/packages/client/src/store/index.js b/packages/client/src/store/index.js
index ebf89e14e3..9f2dbfdcfb 100644
--- a/packages/client/src/store/index.js
+++ b/packages/client/src/store/index.js
@@ -4,6 +4,7 @@ export { routeStore } from "./routes"
export { screenStore } from "./screens"
export { builderStore } from "./builder"
export { dataSourceStore } from "./dataSource"
+export { confirmationStore } from "./confirmation"
// Context stores are layered and duplicated, so it is not a singleton
export { createContextStore } from "./context"
diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js
index 4d2865d586..6a72c494f0 100644
--- a/packages/client/src/utils/buttonActions.js
+++ b/packages/client/src/utils/buttonActions.js
@@ -1,5 +1,5 @@
import { get } from "svelte/store"
-import { routeStore, builderStore, authStore } from "../store"
+import { routeStore, builderStore, confirmationStore } from "../store"
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "../api"
import { ActionTypes } from "../constants"
@@ -68,15 +68,6 @@ const refreshDatasourceHandler = async (action, context) => {
)
}
-const loginHandler = async action => {
- const { email, password } = action.parameters
- await authStore.actions.logIn({ email, password })
-}
-
-const logoutHandler = async () => {
- await authStore.actions.logOut()
-}
-
const handlerMap = {
["Save Row"]: saveRowHandler,
["Delete Row"]: deleteRowHandler,
@@ -85,13 +76,19 @@ const handlerMap = {
["Trigger Automation"]: triggerAutomationHandler,
["Validate Form"]: validateFormHandler,
["Refresh Datasource"]: refreshDatasourceHandler,
- ["Log In"]: loginHandler,
- ["Log Out"]: logoutHandler,
+}
+
+const confirmTextMap = {
+ ["Delete Row"]: "Are you sure you want to delete this row?",
+ ["Save Row"]: "Are you sure you want to save this row?",
+ ["Execute Query"]: "Are you sure you want to execute this query?",
+ ["Trigger Automation"]: "Are you sure you want to trigger this automation?",
}
/**
* Parses an array of actions and returns a function which will execute the
* actions in the current context.
+ * A handler returning `false` is a flag to stop execution of handlers
*/
export const enrichButtonActions = (actions, context) => {
// Prevent button actions in the builder preview
@@ -102,15 +99,44 @@ export const enrichButtonActions = (actions, context) => {
return async () => {
for (let i = 0; i < handlers.length; i++) {
try {
- const result = await handlers[i](actions[i], context)
- // A handler returning `false` is a flag to stop execution of handlers
- if (result === false) {
+ const action = actions[i]
+ const callback = async () => handlers[i](action, context)
+
+ // If this action is confirmable, show confirmation and await a
+ // callback to execute further actions
+ if (action.parameters?.confirm) {
+ const defaultText = confirmTextMap[action["##eventHandlerType"]]
+ const confirmText = action.parameters?.confirmText || defaultText
+ confirmationStore.actions.showConfirmation(
+ action["##eventHandlerType"],
+ confirmText,
+ async () => {
+ // When confirmed, execute this action immediately,
+ // then execute the rest of the actions in the chain
+ const result = await callback()
+ if (result !== false) {
+ const next = enrichButtonActions(actions.slice(i + 1), context)
+ await next()
+ }
+ }
+ )
+
+ // Stop enriching actions when encountering a confirmable action,
+ // as the callback continues the action chain
return
}
+
+ // For non-confirmable actions, execute the handler immediately
+ else {
+ const result = await callback()
+ if (result === false) {
+ return
+ }
+ }
} catch (error) {
console.error("Error while executing button handler")
console.error(error)
- // Stop executing on an error
+ // Stop executing further actions on error
return
}
}