Merge pull request #11260 from Budibase/relationship-picker-filtering

Relationship picker filtering
This commit is contained in:
Andrew Kingston 2023-07-24 14:50:30 +01:00 committed by GitHub
commit 69ab3dfe74
6 changed files with 87 additions and 33 deletions

View File

@ -23,6 +23,7 @@ import BasicColumnEditor from "./controls/ColumnEditor/BasicColumnEditor.svelte"
import GridColumnEditor from "./controls/ColumnEditor/GridColumnEditor.svelte" import GridColumnEditor from "./controls/ColumnEditor/GridColumnEditor.svelte"
import BarButtonList from "./controls/BarButtonList.svelte" import BarButtonList from "./controls/BarButtonList.svelte"
import FieldConfiguration from "./controls/FieldConfiguration/FieldConfiguration.svelte" import FieldConfiguration from "./controls/FieldConfiguration/FieldConfiguration.svelte"
import RelationshipFilterEditor from "./controls/RelationshipFilterEditor.svelte"
const componentMap = { const componentMap = {
text: DrawerBindableInput, text: DrawerBindableInput,
@ -44,6 +45,7 @@ const componentMap = {
schema: SchemaSelect, schema: SchemaSelect,
section: SectionSelect, section: SectionSelect,
filter: FilterEditor, filter: FilterEditor,
"filter/relationship": RelationshipFilterEditor,
url: URLSelect, url: URLSelect,
fieldConfiguration: FieldConfiguration, fieldConfiguration: FieldConfiguration,
columns: ColumnEditor, columns: ColumnEditor,

View File

@ -13,13 +13,14 @@
export let value = [] export let value = []
export let componentInstance export let componentInstance
export let bindings = [] export let bindings = []
export let schema = null
let drawer let drawer
$: tempValue = value $: tempValue = value
$: datasource = getDatasourceForProvider($currentAsset, componentInstance) $: datasource = getDatasourceForProvider($currentAsset, componentInstance)
$: schema = getSchemaForDatasource($currentAsset, datasource)?.schema $: dsSchema = getSchemaForDatasource($currentAsset, datasource)?.schema
$: schemaFields = Object.values(schema || {}) $: schemaFields = Object.values(schema || dsSchema || {})
$: text = getText(value?.filter(filter => filter.field)) $: text = getText(value?.filter(filter => filter.field))
async function saveFilter() { async function saveFilter() {

View File

@ -0,0 +1,35 @@
<script>
import { currentAsset } from "builderStore"
import { findClosestMatchingComponent } from "builderStore/componentUtils"
import {
getDatasourceForProvider,
getSchemaForDatasource,
} from "builderStore/dataBinding"
import { tables } from "stores/backend"
import FilterEditor from "./FilterEditor/FilterEditor.svelte"
export let componentInstance
// Extract which relationship column we're using
$: column = componentInstance.field
// Find the closest parent form
$: form = findClosestMatchingComponent(
$currentAsset.props,
componentInstance._id,
component => component._component.endsWith("/form")
)
// Get that form's schema
$: datasource = getDatasourceForProvider($currentAsset, form)
$: formSchema = getSchemaForDatasource($currentAsset, datasource)?.schema
// Get the schema for the relationship field that this picker is using
$: columnSchema = formSchema?.[column]
// Get the schema for the table on the other side of this relationship
$: linkedTable = $tables.list.find(x => x._id === columnSchema?.tableId)
$: schema = linkedTable?.schema
</script>
<FilterEditor on:change {...$$props} {schema} />

View File

@ -8,16 +8,29 @@
export let componentDefinition export let componentDefinition
export let type export let type
const dispatch = createEventDispatcher()
let drawer let drawer
const dispatch = createEventDispatcher() $: text = getText(value)
const save = () => { const save = () => {
dispatch("change", value) dispatch("change", value)
drawer.hide() drawer.hide()
} }
const getText = rules => {
if (!rules?.length) {
return "No rules set"
} else {
return `${rules.length} rule${rules.length === 1 ? "" : "s"} set`
}
}
</script> </script>
<ActionButton on:click={drawer.show}>Configure validation</ActionButton> <div class="validation-editor">
<ActionButton on:click={drawer.show}>{text}</ActionButton>
</div>
<Drawer bind:this={drawer} title="Validation Rules"> <Drawer bind:this={drawer} title="Validation Rules">
<svelte:fragment slot="description"> <svelte:fragment slot="description">
Configure validation rules for this field. Configure validation rules for this field.
@ -31,3 +44,9 @@
{componentDefinition} {componentDefinition}
/> />
</Drawer> </Drawer>
<style>
.validation-editor :global(.spectrum-ActionButton) {
width: 100%;
}
</style>

View File

@ -3485,6 +3485,16 @@
} }
] ]
}, },
{
"type": "validation/link",
"label": "Validation",
"key": "validation"
},
{
"type": "filter/relationship",
"label": "Filtering",
"key": "filter"
},
{ {
"type": "boolean", "type": "boolean",
"label": "Autocomplete", "label": "Autocomplete",
@ -3496,11 +3506,6 @@
"label": "Disabled", "label": "Disabled",
"key": "disabled", "key": "disabled",
"defaultValue": false "defaultValue": false
},
{
"type": "validation/link",
"label": "Validation",
"key": "validation"
} }
] ]
}, },

View File

@ -1,5 +1,6 @@
<script> <script>
import { CoreSelect, CoreMultiselect } from "@budibase/bbui" import { CoreSelect, CoreMultiselect } from "@budibase/bbui"
import { fetchData } from "@budibase/frontend-core"
import { getContext } from "svelte" import { getContext } from "svelte"
import Field from "./Field.svelte" import Field from "./Field.svelte"
import { FieldTypes } from "../../../constants" import { FieldTypes } from "../../../constants"
@ -14,43 +15,34 @@
export let autocomplete = false export let autocomplete = false
export let defaultValue export let defaultValue
export let onChange export let onChange
export let filter
let fieldState let fieldState
let fieldApi let fieldApi
let fieldSchema let fieldSchema
let options = []
let tableDefinition let tableDefinition
$: multiselect = fieldSchema?.relationshipType !== "one-to-many" $: multiselect = fieldSchema?.relationshipType !== "one-to-many"
$: linkedTableId = fieldSchema?.tableId $: linkedTableId = fieldSchema?.tableId
$: fetchRows(linkedTableId) $: fetch = fetchData({
$: fetchTable(linkedTableId) API,
datasource: {
type: "table",
tableId: linkedTableId,
},
options: {
filter,
limit: 100,
},
})
$: fetch.update({ filter })
$: options = $fetch.rows
$: tableDefinition = $fetch.definition
$: singleValue = flatten(fieldState?.value)?.[0] $: singleValue = flatten(fieldState?.value)?.[0]
$: multiValue = flatten(fieldState?.value) ?? [] $: multiValue = flatten(fieldState?.value) ?? []
$: component = multiselect ? CoreMultiselect : CoreSelect $: component = multiselect ? CoreMultiselect : CoreSelect
$: expandedDefaultValue = expand(defaultValue) $: expandedDefaultValue = expand(defaultValue)
const fetchTable = async id => {
if (id) {
try {
tableDefinition = await API.fetchTableDefinition(id)
} catch (error) {
tableDefinition = null
}
}
}
const fetchRows = async id => {
if (id) {
try {
options = await API.fetchTableData(id)
} catch (error) {
options = []
}
}
}
const flatten = values => { const flatten = values => {
if (!values) { if (!values) {
return [] return []