Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Row actions automation creation #14219

Merged
merged 54 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
6571d61
Persist automation id in row action
adrinr Jul 18, 2024
faf1d67
Create automation
adrinr Jul 18, 2024
2970bfc
Fix update and tests
adrinr Jul 18, 2024
4a8f159
Type sdk couchdb fields
adrinr Jul 19, 2024
eaa38c5
Return automationid from row action api
adrinr Jul 19, 2024
292c873
Check automation creation
adrinr Jul 19, 2024
491266c
Add more tests
adrinr Jul 19, 2024
6761936
Use expectAutomationId()
adrinr Jul 19, 2024
1843233
Undefined context checks
adrinr Jul 19, 2024
b75c8b3
Field readonly
adrinr Jul 18, 2024
a799bc1
Change
adrinr Jul 19, 2024
f91ec1d
Guard readonly and test
adrinr Jul 19, 2024
08a6ac3
Add extra tests
adrinr Jul 19, 2024
6c67aaf
Undo
adrinr Jul 19, 2024
b944390
Fix
adrinr Jul 19, 2024
e0d3855
Display row action trigger info
adrinr Jul 18, 2024
1b2182a
Run without required
adrinr Jul 19, 2024
6221b93
Enrich
adrinr Jul 19, 2024
b7a9692
Display data
adrinr Jul 19, 2024
3c9c988
Populate table name
adrinr Jul 22, 2024
a6f51ca
Display rowaction
adrinr Jul 22, 2024
3bb3376
Format on frontend
adrinr Jul 22, 2024
7574b27
Fix tests
adrinr Jul 22, 2024
3fa7858
Fix references
adrinr Jul 22, 2024
d6e268d
Fix tests
adrinr Jul 22, 2024
cec24fb
Use URLSearchParams
adrinr Jul 22, 2024
286883d
Types
adrinr Jul 22, 2024
9bd22bb
Fix after merge
adrinr Jul 22, 2024
6b58549
Fix issues with circular references and barrel files
adrinr Jul 22, 2024
e5c05c3
Merge pull request #14209 from Budibase/BUDI-8430/rowaction-automatio…
adrinr Jul 22, 2024
b7fc1cd
Merge branch 'master' into feat/row-actions
adrinr Jul 23, 2024
d01bd54
Use name (not display name) on saving
adrinr Jul 22, 2024
703e2c1
Prevent renaming row actions
adrinr Jul 22, 2024
1081d41
Refetch builder data
adrinr Jul 22, 2024
9428172
Prevent duplicate
adrinr Jul 22, 2024
d601400
Don't allow edit or delete actions for row actions
adrinr Jul 23, 2024
d9029da
Don't allow deleting row action automations
adrinr Jul 23, 2024
8678db1
Add tests
adrinr Jul 23, 2024
35bbcce
Return 400 instead of 403
adrinr Jul 23, 2024
b4767ce
Add checks to shared-core
adrinr Jul 23, 2024
af0b69e
Reuse
adrinr Jul 23, 2024
a03094d
Use 422 instead of 400 trying to delete row action automations
adrinr Jul 23, 2024
421e42d
Merge pull request #14218 from Budibase/BUDI-8430/prevent-edits-and-d…
adrinr Jul 23, 2024
fa4629d
Merge branch 'master' into feat/row-actions
adrinr Jul 23, 2024
2d9da6b
Merge branch 'master' into feat/row-actions
adrinr Jul 24, 2024
e161c99
Merge branch 'master' into feat/row-actions
adrinr Jul 24, 2024
b568c9e
Merge branch 'master' into feat/row-actions
adrinr Jul 24, 2024
2e47410
Reuse trigger
adrinr Jul 24, 2024
68018a8
Type
adrinr Jul 24, 2024
8e7c1ba
Merge branch 'master' into feat/row-actions
adrinr Jul 25, 2024
cf4f463
Fix barrel file issues
adrinr Jul 25, 2024
dad27a3
Merge pull request #14238 from Budibase/BUDI-8441/expose-rowaction-de…
adrinr Jul 25, 2024
aafe7a2
Merge branch 'master' into feat/row-actions
adrinr Jul 25, 2024
22f86be
Merge branch 'master' into feat/row-actions
adrinr Jul 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
automationStore,
selectedAutomation,
permissions,
selectedAutomationDisplayData,
} from "stores/builder"
import {
Icon,
Expand All @@ -14,6 +15,7 @@
notifications,
Label,
AbsTooltip,
InlineAlert,
} from "@budibase/bbui"
import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte"
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
Expand Down Expand Up @@ -49,6 +51,8 @@
$: isAppAction && setPermissions(role)
$: isAppAction && getPermissions(automationId)

$: triggerInfo = $selectedAutomationDisplayData?.triggerInfo

async function setPermissions(role) {
if (!role || !automationId) {
return
Expand Down Expand Up @@ -183,6 +187,12 @@
{block}
{webhookModal}
/>
{#if isTrigger && triggerInfo}
<InlineAlert
header={triggerInfo.type}
message={`This trigger is tied to the row action ${triggerInfo.rowAction.name} on your ${triggerInfo.table.name} table`}
/>
{/if}
{#if lastStep}
<Button on:click={() => testDataModal.show()} cta>
Finish and test automation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
// Check the schema to see if required fields have been entered
$: isError =
!isTriggerValid(trigger) ||
!trigger.schema.outputs.required?.every(
!(trigger.schema.outputs.required || []).every(
required => $memoTestData?.[required] || required !== "row"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
contextMenuStore,
} from "stores/builder"
import { notifications, Icon } from "@budibase/bbui"
import { sdk } from "@budibase/shared-core"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import UpdateAutomationModal from "components/automation/AutomationPanel/UpdateAutomationModal.svelte"
import NavItem from "components/common/NavItem.svelte"
Expand Down Expand Up @@ -35,45 +36,53 @@
}

const getContextMenuItems = () => {
return [
{
icon: "Delete",
name: "Delete",
keyBind: null,
visible: true,
disabled: false,
callback: confirmDeleteDialog.show,
},
{
icon: "Edit",
name: "Edit",
keyBind: null,
visible: true,
disabled: false,
callback: updateAutomationDialog.show,
},
{
icon: "Duplicate",
name: "Duplicate",
keyBind: null,
visible: true,
disabled: automation.definition.trigger.name === "Webhook",
callback: duplicateAutomation,
},
{
icon: automation.disabled ? "CheckmarkCircle" : "Cancel",
name: automation.disabled ? "Activate" : "Pause",
keyBind: null,
visible: true,
disabled: false,
callback: () => {
automationStore.actions.toggleDisabled(
automation._id,
automation.disabled
)
},
const isRowAction = sdk.automations.isRowAction(automation)
const result = []
if (!isRowAction) {
result.push(
...[
{
icon: "Delete",
name: "Delete",
keyBind: null,
visible: true,
disabled: false,
callback: confirmDeleteDialog.show,
},
{
icon: "Edit",
name: "Edit",
keyBind: null,
visible: true,
disabled: false,
callback: updateAutomationDialog.show,
},
{
icon: "Duplicate",
name: "Duplicate",
keyBind: null,
visible: true,
disabled: automation.definition.trigger.name === "Webhook",
callback: duplicateAutomation,
},
]
)
}

result.push({
icon: automation.disabled ? "CheckmarkCircle" : "Cancel",
name: automation.disabled ? "Activate" : "Pause",
keyBind: null,
visible: true,
disabled: false,
callback: () => {
automationStore.actions.toggleDisabled(
automation._id,
automation.disabled
)
},
]
})
return result
}

const openContextMenu = e => {
Expand All @@ -89,7 +98,7 @@
on:contextmenu={openContextMenu}
{icon}
iconColor={"var(--spectrum-global-color-gray-900)"}
text={automation.name}
text={automation.displayName}
selected={automation._id === $selectedAutomation?._id}
hovering={automation._id === $contextMenuStore.id}
on:click={() => automationStore.actions.select(automation._id)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
automation.name.toLowerCase().includes(searchString.toLowerCase())
)
})
.map(automation => ({
...automation,
displayName:
$automationStore.automationDisplayData[automation._id].displayName ||
automation.name,
}))
.sort((a, b) => {
const lowerA = a.name.toLowerCase()
const lowerB = b.name.toLowerCase()
const lowerA = a.displayName.toLowerCase()
const lowerB = b.displayName.toLowerCase()
return lowerA > lowerB ? 1 : -1
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@
options={value.enum}
getOptionLabel={(x, idx) =>
value.pretty ? value.pretty[idx] : x}
disabled={value.readonly}
/>
{:else if value.type === "json"}
<Editor
Expand All @@ -884,13 +885,15 @@
mode="json"
value={inputData[key]?.value}
on:change={e => onChange({ [key]: e.detail })}
readOnly={value.readonly}
/>
{:else if value.type === "boolean"}
<div style="margin-top: 10px">
<Checkbox
text={value.title}
value={inputData[key]}
on:change={e => onChange({ [key]: e.detail })}
disabled={value.readonly}
/>
</div>
{:else if value.type === "date"}
Expand All @@ -904,6 +907,7 @@
allowJS={true}
updateOnChange={false}
drawerLeft="260px"
disabled={value.readonly}
>
<DatePicker
value={inputData[key]}
Expand All @@ -915,6 +919,7 @@
on:change={e => onChange({ [key]: e.detail })}
value={inputData[key]}
options={Object.keys(table?.schema || {})}
disabled={value.readonly}
/>
{:else if value.type === "attachment" || value.type === "signature_single"}
<div class="attachment-field-wrapper">
Expand Down Expand Up @@ -1028,6 +1033,7 @@
{isTrigger}
value={inputData[key]}
on:change={e => onChange({ [key]: e.detail })}
disabled={value.readonly}
/>
{:else if value.customType === "webhookUrl"}
<WebhookDisplay value={inputData[key]} />
Expand Down
41 changes: 22 additions & 19 deletions packages/builder/src/stores/builder/automations.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const initialAutomationState = {
ACTION: [],
},
selectedAutomationId: null,
automationDisplayData: {},
}

// If this functions, remove the actions elements
Expand Down Expand Up @@ -58,18 +59,19 @@ const automationActions = store => ({
return response
},
fetch: async () => {
const responses = await Promise.all([
API.getAutomations(),
const [automationResponse, definitions] = await Promise.all([
API.getAutomations({ enrich: true }),
API.getAutomationDefinitions(),
])
store.update(state => {
state.automations = responses[0]
state.automations = automationResponse.automations
state.automations.sort((a, b) => {
return a.name < b.name ? -1 : 1
})
state.automationDisplayData = automationResponse.builderData
state.blockDefinitions = {
TRIGGER: responses[1].trigger,
ACTION: responses[1].action,
TRIGGER: definitions.trigger,
ACTION: definitions.action,
}
return state
})
Expand Down Expand Up @@ -102,19 +104,8 @@ const automationActions = store => ({
},
save: async automation => {
const response = await API.updateAutomation(automation)
store.update(state => {
const updatedAutomation = response.automation
const existingIdx = state.automations.findIndex(
existing => existing._id === automation._id
)
if (existingIdx !== -1) {
state.automations.splice(existingIdx, 1, updatedAutomation)
return state
} else {
state.automations = [...state.automations, updatedAutomation]
}
return state
})

await store.actions.fetch()
return response.automation
},
delete: async automation => {
Expand Down Expand Up @@ -308,7 +299,9 @@ const automationActions = store => ({
if (!automation) {
return
}
delete newAutomation.definition.stepNames[blockId]
if (newAutomation.definition.stepNames) {
delete newAutomation.definition.stepNames[blockId]
}

await store.actions.save(newAutomation)
},
Expand Down Expand Up @@ -384,3 +377,13 @@ export const selectedAutomation = derived(automationStore, $automationStore => {
x => x._id === $automationStore.selectedAutomationId
)
})

export const selectedAutomationDisplayData = derived(
[automationStore, selectedAutomation],
([$automationStore, $selectedAutomation]) => {
if (!$selectedAutomation._id) {
return null
}
return $automationStore.automationDisplayData[$selectedAutomation._id]
}
)
2 changes: 2 additions & 0 deletions packages/builder/src/stores/builder/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
automationStore,
selectedAutomation,
automationHistoryStore,
selectedAutomationDisplayData,
} from "./automations.js"
import { userStore, userSelectedResourceMap, isOnlyUser } from "./users.js"
import { deploymentStore } from "./deployments.js"
Expand Down Expand Up @@ -44,6 +45,7 @@ export {
previewStore,
automationStore,
selectedAutomation,
selectedAutomationDisplayData,
automationHistoryStore,
sortedScreens,
userStore,
Expand Down
9 changes: 7 additions & 2 deletions packages/frontend-core/src/api/automations.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ export const buildAutomationEndpoints = API => ({
/**
* Gets a list of all automations.
*/
getAutomations: async () => {
getAutomations: async ({ enrich }) => {
const params = new URLSearchParams()
if (enrich) {
params.set("enrich", true)
}

return await API.get({
url: "/api/automations",
url: `/api/automations?${params.toString()}`,
})
},

Expand Down
20 changes: 18 additions & 2 deletions packages/server/src/api/controllers/automation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as triggers from "../../automations/triggers"
import { sdk as coreSdk } from "@budibase/shared-core"
import { DocumentType } from "../../db/utils"
import { updateTestHistory, removeDeprecated } from "../../automations/utils"
import { setTestFlag, clearTestFlag } from "../../utilities/redis"
Expand All @@ -11,6 +12,7 @@ import {
AutomationResults,
UserCtx,
DeleteAutomationResponse,
FetchAutomationResponse,
} from "@budibase/types"
import { getActionDefinitions as actionDefs } from "../../automations/actions"
import sdk from "../../sdk"
Expand Down Expand Up @@ -73,8 +75,17 @@ export async function update(ctx: UserCtx) {
builderSocket?.emitAutomationUpdate(ctx, automation)
}

export async function fetch(ctx: UserCtx) {
ctx.body = await sdk.automations.fetch()
export async function fetch(ctx: UserCtx<void, FetchAutomationResponse>) {
const query: { enrich?: string } = ctx.request.query || {}
const enrich = query.enrich === "true"

const automations = await sdk.automations.fetch()
ctx.body = { automations }
if (enrich) {
ctx.body.builderData = await sdk.automations.utils.getBuilderData(
automations
)
}
}

export async function find(ctx: UserCtx) {
Expand All @@ -84,6 +95,11 @@ export async function find(ctx: UserCtx) {
export async function destroy(ctx: UserCtx<void, DeleteAutomationResponse>) {
const automationId = ctx.params.id

const automation = await sdk.automations.get(ctx.params.id)
if (coreSdk.automations.isRowAction(automation)) {
ctx.throw("Row actions automations cannot be deleted", 422)
}

ctx.body = await sdk.automations.remove(automationId, ctx.params.rev)
builderSocket?.emitAutomationDeletion(ctx, automationId)
}
Expand Down
Loading
Loading