refactor switch into a key value handler object
tidy up - remove logs and comments update windowed modals to use postMessage
This commit is contained in:
parent
a18fd99bad
commit
5ebeb6814d
|
@ -33,6 +33,16 @@
|
||||||
.instanceName("Content Placeholder")
|
.instanceName("Content Placeholder")
|
||||||
.json()
|
.json()
|
||||||
|
|
||||||
|
// Messages that can be sent from the iframe preview to the builder
|
||||||
|
// Budibase events are and initalisation events
|
||||||
|
const MessageTypes = {
|
||||||
|
IFRAME_LOADED: "iframe-loaded",
|
||||||
|
READY: "ready",
|
||||||
|
ERROR: "error",
|
||||||
|
BUDIBASE: "type",
|
||||||
|
KEYDOWN: "keydown"
|
||||||
|
}
|
||||||
|
|
||||||
// Construct iframe template
|
// Construct iframe template
|
||||||
$: template = iframeTemplate.replace(
|
$: template = iframeTemplate.replace(
|
||||||
/\{\{ CLIENT_LIB_PATH }}/,
|
/\{\{ CLIENT_LIB_PATH }}/,
|
||||||
|
@ -80,46 +90,44 @@
|
||||||
// Refresh the preview when required
|
// Refresh the preview when required
|
||||||
$: refreshContent(strippedJson)
|
$: refreshContent(strippedJson)
|
||||||
|
|
||||||
onMount(() => {
|
function receiveMessage(message) {
|
||||||
|
const handlers = {
|
||||||
|
[MessageTypes.READY]: () => {
|
||||||
// Initialise the app when mounted
|
// Initialise the app when mounted
|
||||||
iframe.contentWindow.addEventListener(
|
|
||||||
"ready",
|
|
||||||
() => {
|
|
||||||
// Display preview immediately if the intelligent loading feature
|
// Display preview immediately if the intelligent loading feature
|
||||||
// is not supported
|
// is not supported
|
||||||
|
if (!loading) return
|
||||||
|
|
||||||
if (!$store.clientFeatures.intelligentLoading) {
|
if (!$store.clientFeatures.intelligentLoading) {
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
refreshContent(strippedJson)
|
refreshContent(strippedJson)
|
||||||
},
|
},
|
||||||
{ once: true }
|
[MessageTypes.ERROR]: event => {
|
||||||
)
|
|
||||||
|
|
||||||
// Catch any app errors
|
// Catch any app errors
|
||||||
iframe.contentWindow.addEventListener(
|
|
||||||
"error",
|
|
||||||
event => {
|
|
||||||
loading = false
|
loading = false
|
||||||
error = event.detail || "An unknown error occurred"
|
error = event.error || "An unknown error occurred"
|
||||||
},
|
},
|
||||||
{ once: true }
|
[MessageTypes.KEYDOWN]: handleKeydownEvent
|
||||||
)
|
}
|
||||||
|
|
||||||
// Add listener for events sent by client library in preview
|
const messageHandler = handlers[message.data.type] || handleBudibaseEvent
|
||||||
iframe.contentWindow.addEventListener("bb-event", handleBudibaseEvent)
|
messageHandler(message)
|
||||||
iframe.contentWindow.addEventListener("keydown", handleKeydownEvent)
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
window.addEventListener("message", receiveMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Remove all iframe event listeners on component destroy
|
// Remove all iframe event listeners on component destroy
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
if (iframe.contentWindow) {
|
if (iframe.contentWindow) {
|
||||||
iframe.contentWindow.removeEventListener("bb-event", handleBudibaseEvent)
|
window.removeEventListener("message", receiveMessage) //
|
||||||
iframe.contentWindow.removeEventListener("keydown", handleKeydownEvent)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleBudibaseEvent = event => {
|
const handleBudibaseEvent = event => {
|
||||||
const { type, data } = event.detail
|
const { type, data } = event.data
|
||||||
if (type === "select-component" && data.id) {
|
if (type === "select-component" && data.id) {
|
||||||
store.actions.components.select({ _id: data.id })
|
store.actions.components.select({ _id: data.id })
|
||||||
} else if (type === "update-prop") {
|
} else if (type === "update-prop") {
|
||||||
|
@ -151,13 +159,14 @@
|
||||||
store.actions.components.paste(destination, data.mode)
|
store.actions.components.paste(destination, data.mode)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warning(`Client sent unknown event type: ${type}`)
|
console.warn(`Client sent unknown event type: ${type}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeydownEvent = event => {
|
const handleKeydownEvent = event => {
|
||||||
|
const { key } = event.data
|
||||||
if (
|
if (
|
||||||
(event.key === "Delete" || event.key === "Backspace") &&
|
(key === "Delete" || key === "Backspace") &&
|
||||||
selectedComponentId &&
|
selectedComponentId &&
|
||||||
["input", "textarea"].indexOf(
|
["input", "textarea"].indexOf(
|
||||||
iframe.contentWindow.document.activeElement?.tagName.toLowerCase()
|
iframe.contentWindow.document.activeElement?.tagName.toLowerCase()
|
||||||
|
|
|
@ -84,17 +84,20 @@ export default `
|
||||||
if (window.loadBudibase) {
|
if (window.loadBudibase) {
|
||||||
window.loadBudibase()
|
window.loadBudibase()
|
||||||
document.documentElement.classList.add("loaded")
|
document.documentElement.classList.add("loaded")
|
||||||
window.dispatchEvent(new Event("iframe-loaded"))
|
window.parent.postMessage({ type: "iframe-loaded" })
|
||||||
} else {
|
} else {
|
||||||
throw "The client library couldn't be loaded"
|
throw "The client library couldn't be loaded"
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window.dispatchEvent(new CustomEvent("error", { detail: error }))
|
window.parent.postMessage({ type: "error", error })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("message", receiveMessage)
|
window.addEventListener("message", receiveMessage)
|
||||||
window.dispatchEvent(new Event("ready"))
|
window.addEventListener("keydown", evt => {
|
||||||
|
window.parent.postMessage({ type: "keydown", key: event.key })
|
||||||
|
})
|
||||||
|
window.parent.postMessage({ type: "ready" })
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body/>
|
<body/>
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
import { Modal, ModalContent, ActionButton } from "@budibase/bbui"
|
import { Modal, ModalContent, ActionButton } from "@budibase/bbui"
|
||||||
import { onDestroy } from "svelte"
|
import { onDestroy } from "svelte"
|
||||||
|
|
||||||
|
const MessageTypes = {
|
||||||
|
NOTIFICATION: "notification",
|
||||||
|
CLOSE_SCREEN_MODAL: "close-screen-modal",
|
||||||
|
INVALIDATE_DATASOURCE: "invalidate-datasource",
|
||||||
|
}
|
||||||
|
|
||||||
let iframe
|
let iframe
|
||||||
let listenersAttached = false
|
let listenersAttached = false
|
||||||
|
|
||||||
|
@ -21,32 +27,33 @@
|
||||||
notificationStore.actions.send(message, type, icon)
|
notificationStore.actions.send(message, type, icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function receiveMessage(message) {
|
||||||
|
const handlers = {
|
||||||
|
[MessageTypes.NOTIFICATION]: () => {
|
||||||
|
proxyNotification(message.data)
|
||||||
|
},
|
||||||
|
[MessageTypes.CLOSE_SCREEN_MODAL]: peekStore.actions.hidePeek,
|
||||||
|
[MessageTypes.INVALIDATE_DATASOURCE]: () => {
|
||||||
|
invalidateDataSource(message.data)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageHandler = handlers[message.data.type]
|
||||||
|
if (messageHandler) {
|
||||||
|
messageHandler(message)
|
||||||
|
} else {
|
||||||
|
console.warning("Unknown event type", message?.data?.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const attachListeners = () => {
|
const attachListeners = () => {
|
||||||
// Mirror datasource invalidation to keep the parent window up to date
|
// Mirror datasource invalidation to keep the parent window up to date
|
||||||
iframe.contentWindow.addEventListener(
|
window.addEventListener("message", receiveMessage)
|
||||||
"invalidate-datasource",
|
|
||||||
invalidateDataSource
|
|
||||||
)
|
|
||||||
// Listen for a close event to close the screen peek
|
|
||||||
iframe.contentWindow.addEventListener(
|
|
||||||
"close-screen-modal",
|
|
||||||
peekStore.actions.hidePeek
|
|
||||||
)
|
|
||||||
// Proxy notifications back to the parent window instead of iframe
|
|
||||||
iframe.contentWindow.addEventListener("notification", proxyNotification)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
peekStore.actions.hidePeek()
|
peekStore.actions.hidePeek()
|
||||||
iframe.contentWindow.removeEventListener(
|
window.removeEventListener("message", receiveMessage)
|
||||||
"invalidate-datasource",
|
|
||||||
invalidateDataSource
|
|
||||||
)
|
|
||||||
iframe.contentWindow.removeEventListener(
|
|
||||||
"close-screen-modal",
|
|
||||||
peekStore.actions.hidePeek
|
|
||||||
)
|
|
||||||
iframe.contentWindow.removeEventListener("notification", proxyNotification)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFullscreen = () => {
|
const handleFullscreen = () => {
|
||||||
|
|
|
@ -4,11 +4,7 @@ import { findComponentById, findComponentPathById } from "../utils/components"
|
||||||
import { pingEndUser } from "../api"
|
import { pingEndUser } from "../api"
|
||||||
|
|
||||||
const dispatchEvent = (type, data = {}) => {
|
const dispatchEvent = (type, data = {}) => {
|
||||||
window.dispatchEvent(
|
window.parent.postMessage({ type, data })
|
||||||
new CustomEvent("bb-event", {
|
|
||||||
detail: { type, data },
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const createBuilderStore = () => {
|
const createBuilderStore = () => {
|
||||||
|
|
|
@ -26,11 +26,19 @@ const createNotificationStore = () => {
|
||||||
|
|
||||||
// If peeking, pass notifications back to parent window
|
// If peeking, pass notifications back to parent window
|
||||||
if (get(routeStore).queryParams?.peek) {
|
if (get(routeStore).queryParams?.peek) {
|
||||||
window.dispatchEvent(
|
window.parent.postMessage({
|
||||||
new CustomEvent("notification", {
|
type: "notification",
|
||||||
detail: { message, type, icon },
|
detail: {
|
||||||
|
message,
|
||||||
|
type,
|
||||||
|
icon,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
)
|
// window.dispatchEvent(
|
||||||
|
// new CustomEvent("notification", {
|
||||||
|
// detail: { message, type, icon },
|
||||||
|
// })
|
||||||
|
// )
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,10 @@ function copyExistingPropsOver(
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
export function finaliseExternalTables(tables: { [key: string]: any }, entities: { [key: string]: any }) {
|
export function finaliseExternalTables(
|
||||||
|
tables: { [key: string]: any },
|
||||||
|
entities: { [key: string]: any }
|
||||||
|
) {
|
||||||
const finalTables: { [key: string]: any } = {}
|
const finalTables: { [key: string]: any } = {}
|
||||||
const errors: { [key: string]: string } = {}
|
const errors: { [key: string]: string } = {}
|
||||||
for (let [name, table] of Object.entries(tables)) {
|
for (let [name, table] of Object.entries(tables)) {
|
||||||
|
|
Loading…
Reference in New Issue