Add filtering to repeaters

This commit is contained in:
Andrew Kingston 2021-02-11 13:03:22 +00:00
parent 9dc94fbed6
commit 1a00fbacde
4 changed files with 100 additions and 3 deletions

View File

@ -0,0 +1,75 @@
<script>
import { Button, Drawer, Spacer } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
import { notifier } from "builderStore/store/notifications"
import {
getDatasourceForProvider,
getSchemaForDatasource,
} from "builderStore/dataBinding"
import SaveFields from "./EventsEditor/actions/SaveFields.svelte"
const dispatch = createEventDispatcher()
export let value = {}
export let componentInstance
let drawer
let tempValue = value
$: schemaFields = getSchemaFields(componentInstance)
const getSchemaFields = component => {
const datasource = getDatasourceForProvider(component)
const { schema } = getSchemaForDatasource(datasource)
return Object.values(schema || {})
}
const saveFilter = async () => {
dispatch("change", tempValue)
notifier.success("Filters saved.")
drawer.hide()
}
const onFieldsChanged = event => {
tempValue = event.detail
}
</script>
<Button secondary wide on:click={drawer.show}>Define Filters</Button>
<Drawer bind:this={drawer} title={'Filtering'}>
<heading slot="buttons">
<Button thin blue on:click={saveFilter}>Save</Button>
</heading>
<div slot="body">
<div class="root">
{#if !Object.keys(tempValue || {}).length}
<p>Add your first filter column.</p>
<Spacer small />
{/if}
<div class="fields">
<SaveFields
parameterFields={value}
{schemaFields}
on:fieldschanged={onFieldsChanged} />
</div>
</div>
</div>
</Drawer>
<style>
.root {
padding: var(--spacing-m);
min-height: 40vh;
}
p {
margin: 0 0 var(--spacing-s) 0;
}
.fields {
display: grid;
column-gap: var(--spacing-s);
row-gap: var(--spacing-s);
grid-template-columns: auto 1fr auto 1fr auto;
align-items: baseline;
}
</style>

View File

@ -18,6 +18,7 @@
import MultiFieldSelect from "./PropertyControls/MultiFieldSelect.svelte" import MultiFieldSelect from "./PropertyControls/MultiFieldSelect.svelte"
import SchemaSelect from "./PropertyControls/SchemaSelect.svelte" import SchemaSelect from "./PropertyControls/SchemaSelect.svelte"
import EventsEditor from "./PropertyControls/EventsEditor" import EventsEditor from "./PropertyControls/EventsEditor"
import FilterEditor from "./PropertyControls/FilterEditor.svelte"
import ScreenSelect from "./PropertyControls/ScreenSelect.svelte" import ScreenSelect from "./PropertyControls/ScreenSelect.svelte"
import DetailScreenSelect from "./PropertyControls/DetailScreenSelect.svelte" import DetailScreenSelect from "./PropertyControls/DetailScreenSelect.svelte"
import { IconSelect } from "./PropertyControls/IconSelect" import { IconSelect } from "./PropertyControls/IconSelect"
@ -73,6 +74,7 @@
field: FieldSelect, field: FieldSelect,
multifield: MultiFieldSelect, multifield: MultiFieldSelect,
schema: SchemaSelect, schema: SchemaSelect,
filter: FilterEditor,
"field/string": StringFieldSelect, "field/string": StringFieldSelect,
"field/number": NumberFieldSelect, "field/number": NumberFieldSelect,
"field/options": OptionsFieldSelect, "field/options": OptionsFieldSelect,

View File

@ -118,6 +118,11 @@
"label": "Empty Text", "label": "Empty Text",
"key": "noRowsMessage", "key": "noRowsMessage",
"defaultValue": "No rows found." "defaultValue": "No rows found."
},
{
"type": "filter",
"label": "Filtering",
"key": "filter"
} }
] ]
}, },

View File

@ -4,6 +4,7 @@
export let datasource export let datasource
export let noRowsMessage export let noRowsMessage
export let filter
const { API, styleable, Provider, builderStore, ActionTypes } = getContext( const { API, styleable, Provider, builderStore, ActionTypes } = getContext(
"sdk" "sdk"
@ -13,6 +14,7 @@
let loaded = false let loaded = false
$: fetchData(datasource) $: fetchData(datasource)
$: filteredRows = filterRows(rows, filter)
$: actions = [ $: actions = [
{ {
type: ActionTypes.RefreshDatasource, type: ActionTypes.RefreshDatasource,
@ -21,21 +23,34 @@
}, },
] ]
async function fetchData(datasource) { const fetchData = async datasource => {
if (!isEmpty(datasource)) { if (!isEmpty(datasource)) {
rows = await API.fetchDatasource(datasource) rows = await API.fetchDatasource(datasource)
} }
loaded = true loaded = true
} }
const filterRows = (rows, filter) => {
if (!Object.keys(filter || {}).length) {
return rows
}
let filteredData = [...rows]
Object.keys(filter).forEach(field => {
filteredData = filteredData.filter(row => {
return row[field] === filter[field].value
})
})
return filteredData
}
</script> </script>
<Provider {actions}> <Provider {actions}>
<div use:styleable={$component.styles}> <div use:styleable={$component.styles}>
{#if rows.length > 0} {#if filteredRows.length > 0}
{#if $component.children === 0 && $builderStore.inBuilder} {#if $component.children === 0 && $builderStore.inBuilder}
<p><i class="ri-image-line" />Add some components to display.</p> <p><i class="ri-image-line" />Add some components to display.</p>
{:else} {:else}
{#each rows as row} {#each filteredRows as row}
<Provider data={row}> <Provider data={row}>
<slot /> <slot />
</Provider> </Provider>