diff --git a/.github/workflows/readme-openapi.yml b/.github/workflows/readme-openapi.yml
index 14e9887dd6..b52787934f 100644
--- a/.github/workflows/readme-openapi.yml
+++ b/.github/workflows/readme-openapi.yml
@@ -20,9 +20,4 @@ jobs:
- run: yarn --frozen-lockfile
- name: update specs
- run: cd packages/server && yarn specs
-
- - name: Run `openapi` command
- uses: readmeio/rdme@v8
- with:
- rdme: openapi specs/openapi.yaml --key=${{ secrets.README_API_KEY }} --id=6728a74f5918b50036c61841
+ run: cd packages/server && yarn specs && openapi specs/openapi.yaml --key=${{ secrets.README_API_KEY }} --id=6728a74f5918b50036c61841
diff --git a/lerna.json b/lerna.json
index afd0db6374..d893fc97bd 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
- "version": "3.2.26",
+ "version": "3.2.27",
"npmClient": "yarn",
"concurrency": 20,
"command": {
diff --git a/packages/bbui/src/Form/Core/CheckboxGroup.svelte b/packages/bbui/src/Form/Core/CheckboxGroup.svelte
index d1a107fcc5..5aca7911e8 100644
--- a/packages/bbui/src/Form/Core/CheckboxGroup.svelte
+++ b/packages/bbui/src/Form/Core/CheckboxGroup.svelte
@@ -13,9 +13,8 @@
const dispatch = createEventDispatcher()
- const onChange = e => {
- const optionValue = e.target.value
- if (e.target.checked && !value.includes(optionValue)) {
+ const onChange = optionValue => {
+ if (!value.includes(optionValue)) {
dispatch("change", [...value, optionValue])
} else {
dispatch(
@@ -39,10 +38,9 @@
class="spectrum-Checkbox spectrum-Checkbox--sizeM spectrum-FieldGroup-item"
>
onChange(optionValue)}
type="checkbox"
class="spectrum-Checkbox-input"
- value={optionValue}
checked={value.includes(optionValue)}
{disabled}
/>
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/BranchNode.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/BranchNode.svelte
index 670067ea26..c9205d0254 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/BranchNode.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/BranchNode.svelte
@@ -19,7 +19,7 @@
import FlowItemHeader from "./FlowItemHeader.svelte"
import FlowItemActions from "./FlowItemActions.svelte"
import { automationStore, selectedAutomation } from "stores/builder"
- import { QueryUtils } from "@budibase/frontend-core"
+ import { QueryUtils, Utils } from "@budibase/frontend-core"
import { cloneDeep } from "lodash/fp"
import { createEventDispatcher, getContext } from "svelte"
import DragZone from "./DragZone.svelte"
@@ -36,13 +36,11 @@
const view = getContext("draggableView")
let drawer
- let condition
let open = true
let confirmDeleteModal
$: branch = step.inputs?.branches?.[branchIdx]
- $: editableConditionUI = cloneDeep(branch.conditionUI || {})
- $: condition = QueryUtils.buildQuery(editableConditionUI)
+ $: editableConditionUI = branch.conditionUI || {}
// Parse all the bindings into fields for the condition builder
$: schemaFields = bindings.map(binding => {
@@ -80,9 +78,10 @@
slot="buttons"
on:click={() => {
drawer.hide()
+ const updatedConditionsUI = Utils.parseFilter(editableConditionUI)
dispatch("change", {
- conditionUI: editableConditionUI,
- condition,
+ conditionUI: updatedConditionsUI,
+ condition: QueryUtils.buildQuery(updatedConditionsUI),
})
}}
>
diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte
index 3faf9140f4..ab01b56152 100644
--- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte
+++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte
@@ -594,10 +594,11 @@
}
function saveFilters(key) {
- const query = QueryUtils.buildQuery(tempFilters)
+ const update = Utils.parseFilter(tempFilters)
+ const query = QueryUtils.buildQuery(update)
onChange({
[key]: query,
- [`${key}-def`]: tempFilters, // need to store the builder definition in the automation
+ [`${key}-def`]: update, // need to store the builder definition in the automation
})
drawer.hide()
diff --git a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte
index c6103b1697..d4a71c9ef8 100644
--- a/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte
+++ b/packages/builder/src/components/backend/DataTable/buttons/TableFilterButton.svelte
@@ -4,7 +4,7 @@
import FilterBuilder from "components/design/settings/controls/FilterEditor/FilterBuilder.svelte"
import { getUserBindings } from "dataBinding"
import { makePropSafe } from "@budibase/string-templates"
- import { search } from "@budibase/frontend-core"
+ import { search, Utils } from "@budibase/frontend-core"
import { tables } from "stores/builder"
import DetailPopover from "components/common/DetailPopover.svelte"
@@ -73,7 +73,7 @@
cta
slot="buttons"
on:click={() => {
- dispatch("change", localFilters)
+ dispatch("change", Utils.parseFilter(localFilters))
popover.hide()
}}
>
diff --git a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterEditor.svelte b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterEditor.svelte
index c48cc3b8ce..b8a6b86b4d 100644
--- a/packages/builder/src/components/design/settings/controls/FilterEditor/FilterEditor.svelte
+++ b/packages/builder/src/components/design/settings/controls/FilterEditor/FilterEditor.svelte
@@ -10,7 +10,7 @@
import { getDatasourceForProvider, getSchemaForDatasource } from "dataBinding"
import FilterBuilder from "./FilterBuilder.svelte"
import { tables, selectedScreen } from "stores/builder"
- import { search } from "@budibase/frontend-core"
+ import { search, Utils } from "@budibase/frontend-core"
import { utils } from "@budibase/shared-core"
const dispatch = createEventDispatcher()
@@ -33,7 +33,8 @@
$: text = getText(value)
async function saveFilter() {
- dispatch("change", localFilters)
+ const update = Utils.parseFilter(localFilters)
+ dispatch("change", update)
notifications.success("Filters saved")
drawer.hide()
}
diff --git a/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte
index 4ab01de17d..28858f3112 100644
--- a/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte
+++ b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte
@@ -6,6 +6,7 @@
QueryUtils,
Constants,
CoreFilterBuilder,
+ Utils,
} from "@budibase/frontend-core"
import Button from "../Button.svelte"
@@ -95,7 +96,7 @@
}
const updateQuery = () => {
- filters = editableFilters
+ filters = Utils.parseFilter(editableFilters)
}
onDestroy(() => {
diff --git a/packages/frontend-core/src/components/CoreFilterBuilder.svelte b/packages/frontend-core/src/components/CoreFilterBuilder.svelte
index 3aff981082..2bf40bda37 100644
--- a/packages/frontend-core/src/components/CoreFilterBuilder.svelte
+++ b/packages/frontend-core/src/components/CoreFilterBuilder.svelte
@@ -407,6 +407,7 @@
/>
new Promise(resolve => setTimeout(resolve, ms))
@@ -351,3 +352,27 @@ export const buildMultiStepFormBlockDefaultProps = props => {
title,
}
}
+
+/**
+ * Parse out empty or invalid UI filters and clear empty groups
+ * @param {Object} filter UI filter
+ * @returns {Object} parsed filter
+ */
+export function parseFilter(filter) {
+ if (!filter?.groups) {
+ return filter
+ }
+
+ const update = cloneDeep(filter)
+
+ update.groups = update.groups
+ .map(group => {
+ group.filters = group.filters.filter(filter => {
+ return filter.field && filter.operator
+ })
+ return group.filters.length ? group : null
+ })
+ .filter(group => group)
+
+ return update
+}
diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts
index 61950fd523..a023015b7e 100644
--- a/packages/shared-core/src/filters.ts
+++ b/packages/shared-core/src/filters.ts
@@ -298,7 +298,8 @@ export class ColumnSplitter {
function buildCondition(filter: undefined): undefined
function buildCondition(filter: SearchFilter): SearchFilters
function buildCondition(filter?: SearchFilter): SearchFilters | undefined {
- if (!filter) {
+ // Ignore empty or invalid filters
+ if (!filter || !filter?.operator || !filter?.field) {
return
}
@@ -475,7 +476,6 @@ export function buildQuery(
if (group.logicalOperator) {
operator = logicalOperatorFromUI(group.logicalOperator)
}
-
return {
[operator]: { conditions: filters.map(buildCondition).filter(f => f) },
}