Allow table with search block to render correct components for all relevant field types

This commit is contained in:
Andrew Kingston 2021-11-03 11:58:06 +00:00
parent 73d5d1289b
commit 7ec5c2b1f2
3 changed files with 129 additions and 60 deletions

View File

@ -2626,13 +2626,6 @@
"key": "rowCount",
"defaultValue": 8
},
{
"type": "multifield",
"label": "Table Columns",
"key": "tableColumns",
"dependsOn": "dataSource",
"placeholder": "All columns"
},
{
"type": "select",
"label": "Size",
@ -2649,14 +2642,21 @@
}
]
},
{
"type": "multifield",
"label": "Table Columns",
"key": "tableColumns",
"dependsOn": "dataSource",
"placeholder": "All columns"
},
{
"type": "boolean",
"label": "Quiet",
"label": "Quiet table variant",
"key": "quiet"
},
{
"type": "boolean",
"label": "Auto Columns",
"label": "Show auto columns",
"key": "showAutoColumns",
"defaultValue": false
}

View File

@ -2,7 +2,6 @@
import { getContext, setContext } from "svelte"
const component = getContext("component")
const { styleable } = getContext("sdk")
// We need to set a block context to know we're inside a block, but also
// to be able to reference the actual component ID of the block from
@ -10,6 +9,4 @@
setContext("block", { id: $component.id })
</script>
<div use:styleable={$component.styles}>
<slot />
</div>
<slot />

View File

@ -1,4 +1,5 @@
<script>
import { onMount, getContext } from "svelte"
import Block from "components/Block.svelte"
import BlockComponent from "components/BlockComponent.svelte"
import { Heading } from "@budibase/bbui"
@ -16,85 +17,156 @@
export let quiet
export let size
const { API, styleable } = getContext("sdk")
const context = getContext("context")
const component = getContext("component")
const schemaComponentMap = {
string: "stringfield",
options: "optionsfield",
number: "numberfield",
datetime: "datetimefield",
boolean: "booleanfield",
}
let formId
let dataProviderId
let schema
$: enrichedFilter = enrichFilter(filter, searchColumns, formId)
$: enrichedSearchColumns = enrichSearchColumns(searchColumns, schema)
$: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId)
// Enrich the default filter with the specified search fields
const enrichFilter = (filter, searchColumns, formId) => {
const enrichFilter = (filter, columns, formId) => {
let enrichedFilter = [...(filter || [])]
searchColumns?.forEach(column => {
columns?.forEach(column => {
enrichedFilter.push({
field: column,
field: column.name,
operator: "equal",
type: "string",
valueType: "Binding",
value: `{{ [${formId}].[${column}] }}`,
value: `{{ [${formId}].[${column.name}] }}`,
})
})
return enrichedFilter
}
// Determine data types for search fields and only use those that are valid
const enrichSearchColumns = (searchColumns, schema) => {
let enrichedColumns = []
searchColumns?.forEach(column => {
const schemaType = schema?.[column]?.type
const componentType = schemaComponentMap[schemaType]
if (componentType) {
enrichedColumns.push({
name: column,
componentType,
})
}
})
return enrichedColumns
}
// Load the datasource schema on mount so we can determine column types
onMount(async () => {
if (dataSource) {
schema = await API.fetchDatasourceSchema(dataSource)
}
})
</script>
<Block>
<BlockComponent type="form" bind:id={formId} props={{ dataSource }}>
{#if searchColumns?.length}
<div class="search">
{#if title}
<div class={size} use:styleable={$component.styles}>
<BlockComponent type="form" bind:id={formId} props={{ dataSource }}>
{#if title || enrichedSearchColumns?.length}
<div class="header">
<div class="title">
<Heading>{title}</Heading>
<Heading>{title || ""}</Heading>
</div>
{/if}
{#each searchColumns as column}
<BlockComponent
type="stringfield"
props={{
field: column,
placeholder: column,
label: column,
}}
/>
{/each}
</div>
{/if}
<BlockComponent
type="dataprovider"
bind:id={dataProviderId}
props={{
dataSource,
filter: enrichedFilter,
sortColumn,
sortOrder,
paginate,
limit: rowCount,
}}
>
{#if enrichedSearchColumns?.length}
<div class="search" class:mobile={$context.device.mobile}>
{#each enrichedSearchColumns as column}
<BlockComponent
type={column.componentType}
props={{
field: column.name,
placeholder: column.name,
text: column.name,
autoWidth: true,
}}
/>
{/each}
</div>
{/if}
</div>
{/if}
<BlockComponent
type="table"
type="dataprovider"
bind:id={dataProviderId}
props={{
dataProvider: `{{ literal [${dataProviderId}] }}`,
columns: tableColumns,
showAutoColumns,
rowCount,
quiet,
size,
dataSource,
filter: enrichedFilter,
sortColumn,
sortOrder,
paginate,
limit: rowCount,
}}
/>
>
<BlockComponent
type="table"
props={{
dataProvider: `{{ literal [${dataProviderId}] }}`,
columns: tableColumns,
showAutoColumns,
rowCount,
quiet,
size,
}}
/>
</BlockComponent>
</BlockComponent>
</BlockComponent>
</div>
</Block>
<style>
.search {
.header {
display: flex;
flex-direction: row;
justify-content: flex-end;
justify-content: space-between;
align-items: center;
gap: 20px;
flex-wrap: wrap;
margin-bottom: 20px;
gap: 10px;
}
.title {
flex: 1 1 auto;
}
.search {
flex: 0 0 auto;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
gap: 10px;
max-width: 100%;
flex-wrap: wrap;
}
.search :global(.component > *) {
width: 200px;
}
.search :global(.spectrum-InputGroup .spectrum-InputGroup-input) {
width: 100%;
}
.search :global(.spectrum-InputGroup) {
min-width: 0;
}
.search.mobile {
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
position: relative;
width: 100%;
}
.search.mobile :global(.component > *) {
width: 100%;
}
</style>