Allow table with search block to render correct components for all relevant field types
This commit is contained in:
parent
73d5d1289b
commit
7ec5c2b1f2
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue