This commit is contained in:
Dean 2025-04-22 15:25:41 +01:00
parent 20d90efae7
commit d37731d5a3
8 changed files with 53 additions and 105 deletions

View File

@ -34,7 +34,7 @@ import FormStepControls from "./controls/FormStepControls.svelte"
import PaywalledSetting from "./controls/PaywalledSetting.svelte" import PaywalledSetting from "./controls/PaywalledSetting.svelte"
import TableConditionEditor from "./controls/TableConditionEditor.svelte" import TableConditionEditor from "./controls/TableConditionEditor.svelte"
import MultilineDrawerBindableInput from "@/components/common/MultilineDrawerBindableInput.svelte" import MultilineDrawerBindableInput from "@/components/common/MultilineDrawerBindableInput.svelte"
import EmbeddedDatasourceSelect from "./controls/EmbeddedDatasourceSelect.svelte" import FilterableSelect from "./controls/FilterableSelect.svelte"
const componentMap = { const componentMap = {
text: DrawerBindableInput, text: DrawerBindableInput,
@ -44,7 +44,7 @@ const componentMap = {
radio: RadioGroup, radio: RadioGroup,
dataSource: DataSourceSelect, dataSource: DataSourceSelect,
"dataSource/s3": S3DataSourceSelect, "dataSource/s3": S3DataSourceSelect,
"dataSource/embedded": EmbeddedDatasourceSelect, "dataSource/filterable": FilterableSelect,
dataProvider: DataProviderSelect, dataProvider: DataProviderSelect,
boolean: Checkbox, boolean: Checkbox,
number: Stepper, number: Stepper,

View File

@ -1,62 +0,0 @@
<script lang="ts">
import { Select } from "@budibase/bbui"
import { componentStore, selectedScreen } from "@/stores/builder"
import { findAllComponents, getComponentContexts } from "@/helpers/components"
import { makePropSafe as safe } from "@budibase/string-templates"
import { createEventDispatcher } from "svelte"
import { extractLiteralHandlebarsID } from "@/dataBinding"
import { type Component } from "@budibase/types"
export let value: string | undefined = undefined
const dispatch = createEventDispatcher()
let providersComps: Component[]
let providers: { label: string; value: string; subtitle: string }[]
// Load the component for processing
$: targetId = extractLiteralHandlebarsID(value)
// Refresh datasources if the target is altered
$: if (targetId) {
providersComps = loadProviderComponents()
providers = buildProviders()
}
const handleSelected = (selected: string) => {
dispatch("change", selected)
}
// Components that surface data
const buildProviders = () => {
if (!$selectedScreen) return []
return providersComps.map(provider => ({
label: provider._instanceName,
value: `{{ literal ${safe(provider._id)} }}`,
subtitle: `${
provider?.dataSource?.label || provider?.table?.label || "-"
}`,
}))
}
const loadProviderComponents = () => {
if (!$selectedScreen) return []
return findAllComponents($selectedScreen.props).filter(component => {
if (component._id === $componentStore.selectedComponentId) return false
const contexts = getComponentContexts(component._component)
const targetContexts = contexts.filter(ctx =>
ctx.actions?.find(act => act.type === "RefreshDatasource")
)
return !!targetContexts.length
})
}
</script>
<Select
{value}
options={providers}
on:change={e => {
handleSelected(e.detail)
}}
/>

View File

@ -0,0 +1,36 @@
<script lang="ts">
import { Select } from "@budibase/bbui"
import { selectedScreen } from "@/stores/builder"
import { findAllComponents, getComponentContexts } from "@/helpers/components"
import { makePropSafe as safe } from "@budibase/string-templates"
import { type Component } from "@budibase/types"
export let value: string | undefined = undefined
$: providers = getProviders($selectedScreen?.props)
const getProviders = (rootComponent: Component | undefined) => {
if (!rootComponent) {
return []
}
return findAllComponents(rootComponent)
.filter(component => {
return getComponentContexts(component._component).some(ctx =>
ctx.actions?.find(
act =>
act.type === "AddDataProviderQueryExtension" ||
act.type === "AddDataProviderFilterExtension"
)
)
})
.map(provider => ({
label: provider._instanceName,
value: `{{ literal ${safe(provider._id)} }}`,
subtitle: `${
provider?.dataSource?.label || provider?.table?.label || "-"
}`,
}))
}
</script>
<Select {value} options={providers} on:change />

View File

@ -212,10 +212,8 @@ export class ComponentStore extends BudiStore<ComponentState> {
} }
const def = this.getDefinition(enrichedComponent?._component) const def = this.getDefinition(enrichedComponent?._component)
const filterableTypes = def?.settings?.filter( const filterableTypes = def?.settings?.filter(setting =>
setting => ["filter", "filter/relationship"].includes(setting?.type)
setting?.type?.startsWith("filter") &&
setting?.type !== "filterConfiguration"
) )
for (let setting of filterableTypes || []) { for (let setting of filterableTypes || []) {
const isLegacy = Array.isArray(enrichedComponent[setting.key]) const isLegacy = Array.isArray(enrichedComponent[setting.key])

View File

@ -5204,7 +5204,7 @@
"icon": "Data", "icon": "Data",
"illegalChildren": ["section"], "illegalChildren": ["section"],
"hasChildren": true, "hasChildren": true,
"actions": ["RefreshDatasource"], "actions": ["RefreshDatasource", "AddDataProviderQueryExtension"],
"size": { "size": {
"width": 500, "width": 500,
"height": 200 "height": 200
@ -5534,9 +5534,10 @@
"width": 100, "width": 100,
"height": 35 "height": 35
}, },
"new": true,
"settings": [ "settings": [
{ {
"type": "dataSource/embedded", "type": "dataSource/filterable",
"label": "Target component", "label": "Target component",
"required": true, "required": true,
"key": "targetComponent", "key": "targetComponent",
@ -5552,17 +5553,15 @@
}, },
{ {
"type": "boolean", "type": "boolean",
"label": "Persist filter values when a user returns to the screen", "label": "Persist filters",
"key": "persistFilters", "key": "persistFilters",
"wide": true,
"defaultValue": false "defaultValue": false
}, },
{ {
"type": "boolean", "type": "boolean",
"label": "Add a 'Clear filters' button so that user can clear multiple filters at once", "label": "Clear filters",
"key": "showClear", "key": "showClear",
"defaultValue": false, "defaultValue": false
"wide": true
} }
] ]
}, },
@ -7873,20 +7872,9 @@
"type": "array" "type": "array"
} }
] ]
},
{
"type": "static",
"scope": "local",
"values": [
{
"label": "Datasources",
"key": "datasources",
"type": "array"
}
]
} }
], ],
"actions": ["RefreshDatasource", "AddDataProviderQueryExtension"] "actions": ["RefreshDatasource", "AddDataProviderFilterExtension"]
}, },
"bbreferencefield": { "bbreferencefield": {
"devComment": "As bb reference is only used for user subtype for now, we are using user for icon and labels", "devComment": "As bb reference is only used for user subtype for now, we are using user for icon and labels",

View File

@ -109,27 +109,16 @@
} }
const extendFilter = (initialFilter, extensions) => { const extendFilter = (initialFilter, extensions) => {
if (!extensions || !Object.keys(extensions).length) { if (!Object.keys(extensions || {}).length) {
return initialFilter return initialFilter
} }
return {
// Base filter groups: (initialFilter ? [initialFilter] : []).concat(
let extended = { Object.values(extensions)
groups: initialFilter ? [initialFilter] : [], ),
logicalOperator: UILogicalOperator.ALL, logicalOperator: UILogicalOperator.ALL,
onEmptyFilter: EmptyFilterOption.RETURN_NONE, onEmptyFilter: EmptyFilterOption.RETURN_NONE,
} }
// Process and aggregate all filters.
let groups = Object.entries(extensions).map(([_, entry]) => {
// Assuming there should only ever be 1
return entry
})
// Combine all groups into the base
extended.groups = [...extended.groups, ...groups]
return extended
} }
// Provide additional data context for live binding eval // Provide additional data context for live binding eval

View File

@ -229,7 +229,7 @@
} }
.spectrum-Button-label .display { .spectrum-Button-label .display {
color: rgba(179, 222, 254, 1); color: var(--spectrum-global-color-blue-600);
} }
.spectrum-Button--secondary.new-styles { .spectrum-Button--secondary.new-styles {

View File

@ -44,7 +44,6 @@ const createComponentStore = () => {
selectedComponentPath: selectedPath?.map(component => component._id), selectedComponentPath: selectedPath?.map(component => component._id),
mountedComponentCount: Object.keys($store.mountedComponents).length, mountedComponentCount: Object.keys($store.mountedComponents).length,
screenslotInstance: $store.mountedComponents[ScreenslotID], screenslotInstance: $store.mountedComponents[ScreenslotID],
mounted: $store.mountedComponents,
} }
} }
) )