Add filtering to repeaters
This commit is contained in:
parent
9dc94fbed6
commit
1a00fbacde
|
@ -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>
|
|
@ -18,6 +18,7 @@
|
|||
import MultiFieldSelect from "./PropertyControls/MultiFieldSelect.svelte"
|
||||
import SchemaSelect from "./PropertyControls/SchemaSelect.svelte"
|
||||
import EventsEditor from "./PropertyControls/EventsEditor"
|
||||
import FilterEditor from "./PropertyControls/FilterEditor.svelte"
|
||||
import ScreenSelect from "./PropertyControls/ScreenSelect.svelte"
|
||||
import DetailScreenSelect from "./PropertyControls/DetailScreenSelect.svelte"
|
||||
import { IconSelect } from "./PropertyControls/IconSelect"
|
||||
|
@ -73,6 +74,7 @@
|
|||
field: FieldSelect,
|
||||
multifield: MultiFieldSelect,
|
||||
schema: SchemaSelect,
|
||||
filter: FilterEditor,
|
||||
"field/string": StringFieldSelect,
|
||||
"field/number": NumberFieldSelect,
|
||||
"field/options": OptionsFieldSelect,
|
||||
|
|
|
@ -118,6 +118,11 @@
|
|||
"label": "Empty Text",
|
||||
"key": "noRowsMessage",
|
||||
"defaultValue": "No rows found."
|
||||
},
|
||||
{
|
||||
"type": "filter",
|
||||
"label": "Filtering",
|
||||
"key": "filter"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
export let datasource
|
||||
export let noRowsMessage
|
||||
export let filter
|
||||
|
||||
const { API, styleable, Provider, builderStore, ActionTypes } = getContext(
|
||||
"sdk"
|
||||
|
@ -13,6 +14,7 @@
|
|||
let loaded = false
|
||||
|
||||
$: fetchData(datasource)
|
||||
$: filteredRows = filterRows(rows, filter)
|
||||
$: actions = [
|
||||
{
|
||||
type: ActionTypes.RefreshDatasource,
|
||||
|
@ -21,21 +23,34 @@
|
|||
},
|
||||
]
|
||||
|
||||
async function fetchData(datasource) {
|
||||
const fetchData = async datasource => {
|
||||
if (!isEmpty(datasource)) {
|
||||
rows = await API.fetchDatasource(datasource)
|
||||
}
|
||||
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>
|
||||
|
||||
<Provider {actions}>
|
||||
<div use:styleable={$component.styles}>
|
||||
{#if rows.length > 0}
|
||||
{#if filteredRows.length > 0}
|
||||
{#if $component.children === 0 && $builderStore.inBuilder}
|
||||
<p><i class="ri-image-line" />Add some components to display.</p>
|
||||
{:else}
|
||||
{#each rows as row}
|
||||
{#each filteredRows as row}
|
||||
<Provider data={row}>
|
||||
<slot />
|
||||
</Provider>
|
||||
|
|
Loading…
Reference in New Issue