Adding a modal on creation of a webhook automation to make sure the user can setup a schema.
This commit is contained in:
parent
653fb16c86
commit
ec7a4d7f8b
|
@ -11,12 +11,18 @@ const automationActions = store => ({
|
|||
])
|
||||
const jsonResponses = await Promise.all(responses.map(x => x.json()))
|
||||
store.update(state => {
|
||||
let selected = state.selectedAutomation?.automation
|
||||
state.automations = jsonResponses[0]
|
||||
state.blockDefinitions = {
|
||||
TRIGGER: jsonResponses[1].trigger,
|
||||
ACTION: jsonResponses[1].action,
|
||||
LOGIC: jsonResponses[1].logic,
|
||||
}
|
||||
// if previously selected find the new obj and select it
|
||||
if (selected) {
|
||||
selected = jsonResponses[0].filter(automation => automation._id === selected._id)
|
||||
state.selectedAutomation = new Automation(selected[0])
|
||||
}
|
||||
return state
|
||||
})
|
||||
},
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
<script>
|
||||
import { backendUiStore, automationStore } from "builderStore"
|
||||
import CreateWebookModal from "./CreateWebhookModal.svelte"
|
||||
import analytics from "analytics"
|
||||
import { Modal } from "@budibase/bbui"
|
||||
|
||||
export let blockDefinition
|
||||
export let stepId
|
||||
export let blockType
|
||||
|
||||
let modal
|
||||
|
||||
$: blockDefinitions = $automationStore.blockDefinitions
|
||||
$: instanceId = $backendUiStore.selectedDatabase._id
|
||||
$: automation = $automationStore.selectedAutomation?.automation
|
||||
|
@ -18,10 +22,7 @@
|
|||
type: blockType,
|
||||
})
|
||||
if (stepId === blockDefinitions.TRIGGER["WEBHOOK"].stepId) {
|
||||
automationStore.actions.save({
|
||||
instanceId,
|
||||
automation,
|
||||
})
|
||||
modal.show()
|
||||
}
|
||||
analytics.captureEvent("Added Automation Block", {
|
||||
name: blockDefinition.name,
|
||||
|
@ -39,6 +40,9 @@
|
|||
<p>{blockDefinition.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
<Modal bind:this={modal} width="30%">
|
||||
<CreateWebookModal />
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.automation-block {
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
<script>
|
||||
import { store, backendUiStore, automationStore } from "builderStore"
|
||||
import WebhookDisplay from "./WebhookDisplay.svelte"
|
||||
import { ModalContent } from "@budibase/bbui"
|
||||
import { onMount, onDestroy } from "svelte"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
import analytics from "analytics"
|
||||
|
||||
const POLL_RATE_MS = 2500
|
||||
const DEFAULT_SCHEMA_OUTPUT = "Any input allowed"
|
||||
let name
|
||||
let interval
|
||||
let valid = false
|
||||
let schemaURL
|
||||
let schema = DEFAULT_SCHEMA_OUTPUT
|
||||
|
||||
$: instanceId = $backendUiStore.selectedDatabase._id
|
||||
$: appId = $store.appId
|
||||
$: automation = $automationStore.selectedAutomation?.automation
|
||||
|
||||
onMount(async () => {
|
||||
// save the automation initially
|
||||
await automationStore.actions.save({
|
||||
instanceId,
|
||||
automation,
|
||||
})
|
||||
interval = setInterval(async () => {
|
||||
await automationStore.actions.fetch()
|
||||
const outputs = automation?.definition?.trigger.schema.outputs?.properties
|
||||
if (Object.keys(outputs).length !== 0) {
|
||||
schema = cloneDeep(outputs)
|
||||
// clear out the "description" properties
|
||||
for (let key of Object.keys(schema)) {
|
||||
delete schema[key].description
|
||||
}
|
||||
schema = JSON.stringify(schema, null, 2)
|
||||
//schema = schema.replace(/(?:\r\n|\r|\n)/g, "<br />")
|
||||
//console.log(schema)
|
||||
valid = true
|
||||
}
|
||||
}, POLL_RATE_MS)
|
||||
schemaURL = automation?.definition?.trigger?.inputs.schemaUrl
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(interval)
|
||||
})
|
||||
</script>
|
||||
|
||||
<ModalContent
|
||||
title="Webhook Setup"
|
||||
confirmText="Finished"
|
||||
cancelText="Skip"
|
||||
disabled={!valid}>
|
||||
<p class="webhook-exp">To configure a webhook we need to create a schema for your webhook to validate against.
|
||||
Use the URL shown below and send a <b>POST</b> request to it with a JSON body in the format that
|
||||
your webhook should use!</p>
|
||||
<WebhookDisplay value={schemaURL}/>
|
||||
<h5>Schema</h5>
|
||||
<code>
|
||||
{schema}
|
||||
</code>
|
||||
<div slot="footer">
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://docs.budibase.com/automate/steps/triggers">
|
||||
<i class="ri-information-line" />
|
||||
<span>Learn about webhooks</span>
|
||||
</a>
|
||||
</div>
|
||||
</ModalContent>
|
||||
|
||||
<style>
|
||||
a {
|
||||
color: var(--ink);
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
a span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
i {
|
||||
font-size: 20px;
|
||||
margin-right: var(--spacing-m);
|
||||
text-decoration: none;
|
||||
}
|
||||
p {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
text-align: justify;
|
||||
}
|
||||
h5 {
|
||||
margin: 0;
|
||||
}
|
||||
code {
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
color: var(--grey-5);
|
||||
background-color: var(--grey-4);
|
||||
border-radius: 6px;
|
||||
display: block;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,57 @@
|
|||
<script>
|
||||
import { notifier } from "builderStore/store/notifications"
|
||||
import { Input } from "@budibase/bbui"
|
||||
|
||||
export let value
|
||||
|
||||
function fullWebhookURL(uri) {
|
||||
return `http://localhost:4001/${uri}`
|
||||
}
|
||||
|
||||
function copyToClipboard() {
|
||||
const dummy = document.createElement("textarea")
|
||||
document.body.appendChild(dummy)
|
||||
dummy.value = fullWebhookURL(value)
|
||||
dummy.select()
|
||||
document.execCommand("copy")
|
||||
document.body.removeChild(dummy)
|
||||
notifier.success(`URL copied to clipboard`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="copy-area">
|
||||
<Input
|
||||
disabled="true"
|
||||
thin
|
||||
value={fullWebhookURL(value)}/>
|
||||
<span
|
||||
class="copy-btn"
|
||||
on:click={() => copyToClipboard()}>
|
||||
<i class="ri-clipboard-line copy-icon" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.copy-area {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
position: absolute;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background: white;
|
||||
right: var(--spacing-s);
|
||||
bottom: 9px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copy-btn:hover {
|
||||
background-color: var(--grey-3);
|
||||
}
|
||||
</style>
|
|
@ -3,7 +3,7 @@
|
|||
import RowSelector from "./ParamInputs/RowSelector.svelte"
|
||||
import { Button, Input, TextArea, Select, Label } from "@budibase/bbui"
|
||||
import { automationStore } from "builderStore"
|
||||
import { notifier } from "builderStore/store/notifications"
|
||||
import WebhookDisplay from "../AutomationPanel/BlockList/WebhookDisplay.svelte"
|
||||
import BindableInput from "../../userInterface/BindableInput.svelte"
|
||||
|
||||
export let block
|
||||
|
@ -43,20 +43,6 @@
|
|||
}
|
||||
return bindings
|
||||
}
|
||||
|
||||
function fullWebhookURL(uri) {
|
||||
return `http://localhost:4001/${uri}`
|
||||
}
|
||||
|
||||
function copyToClipboard(input) {
|
||||
const dummy = document.createElement("textarea")
|
||||
document.body.appendChild(dummy)
|
||||
dummy.value = input
|
||||
dummy.select()
|
||||
document.execCommand("copy")
|
||||
document.body.removeChild(dummy)
|
||||
notifier.success(`URL copied to clipboard`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container" data-cy="automation-block-setup">
|
||||
|
@ -80,17 +66,7 @@
|
|||
{:else if value.customType === 'row'}
|
||||
<RowSelector bind:value={block.inputs[key]} {bindings} />
|
||||
{:else if value.customType === 'webhookUrl'}
|
||||
<div class="copy-area">
|
||||
<Input
|
||||
disabled="true"
|
||||
thin
|
||||
value={fullWebhookURL(block.inputs[key])} />
|
||||
<span
|
||||
class="copy-btn"
|
||||
on:click={() => copyToClipboard(fullWebhookURL(block.inputs[key]))}>
|
||||
<i class="ri-clipboard-line copy-icon" />
|
||||
</span>
|
||||
</div>
|
||||
<WebhookDisplay value={block.inputs[key]}/>
|
||||
{:else if value.type === 'string' || value.type === 'number'}
|
||||
<BindableInput
|
||||
type="string"
|
||||
|
@ -119,27 +95,4 @@
|
|||
padding: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.copy-area {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
position: absolute;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background: white;
|
||||
right: var(--spacing-s);
|
||||
bottom: 9px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copy-btn:hover {
|
||||
background-color: var(--grey-4);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -41,6 +41,8 @@ function cleanAutomationInputs(automation) {
|
|||
* written to DB (this does not write to DB as it would be wasteful to repeat).
|
||||
*/
|
||||
async function checkForWebhooks({ user, oldAuto, newAuto }) {
|
||||
const oldTrigger = oldAuto ? oldAuto.definition.trigger : null
|
||||
const newTrigger = newAuto ? newAuto.definition.trigger : null
|
||||
function isWebhookTrigger(auto) {
|
||||
return (
|
||||
auto &&
|
||||
|
@ -52,21 +54,19 @@ async function checkForWebhooks({ user, oldAuto, newAuto }) {
|
|||
if (
|
||||
isWebhookTrigger(oldAuto) &&
|
||||
!isWebhookTrigger(newAuto) &&
|
||||
oldAuto.definition.trigger.webhook
|
||||
oldTrigger.webhookId
|
||||
) {
|
||||
let db = new CouchDB(user.instanceId)
|
||||
// need to get the webhook to get the rev
|
||||
const webhook = await db.get(oldTrigger.webhookId)
|
||||
const ctx = {
|
||||
user,
|
||||
params: {
|
||||
id: oldAuto.definition.trigger.webhook.id,
|
||||
rev: oldAuto.definition.trigger.webhook.rev,
|
||||
},
|
||||
params: { id: webhook._id, rev: webhook._rev },
|
||||
}
|
||||
// reset the inputs to remove the URLs
|
||||
if (newAuto && newAuto.definition.trigger) {
|
||||
const trigger = newAuto.definition.trigger
|
||||
delete trigger.webhook
|
||||
delete trigger.inputs.schemaUrl
|
||||
delete trigger.inputs.triggerUrl
|
||||
// might be updating - reset the inputs to remove the URLs
|
||||
if (newTrigger) {
|
||||
delete newTrigger.webhookId
|
||||
newTrigger.inputs = {}
|
||||
}
|
||||
await webhooks.destroy(ctx)
|
||||
}
|
||||
|
@ -83,10 +83,9 @@ async function checkForWebhooks({ user, oldAuto, newAuto }) {
|
|||
},
|
||||
}
|
||||
await webhooks.save(ctx)
|
||||
const id = ctx.body.webhook._id,
|
||||
rev = ctx.body.webhook._rev
|
||||
newAuto.definition.trigger.webhook = { id, rev }
|
||||
newAuto.definition.trigger.inputs = {
|
||||
const id = ctx.body.webhook._id
|
||||
newTrigger.webhookId = id
|
||||
newTrigger.inputs = {
|
||||
schemaUrl: `api/webhooks/schema/${user.instanceId}/${id}`,
|
||||
triggerUrl: `api/webhooks/trigger/${user.instanceId}/${id}`,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue