Merge pull request #11260 from Budibase/relationship-picker-filtering
Relationship picker filtering
This commit is contained in:
commit
69ab3dfe74
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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} />
|
|
@ -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>
|
||||||
|
|
|
@ -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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 []
|
||||||
|
|
Loading…
Reference in New Issue