Update bindable properties to handle new data provider

This commit is contained in:
Andrew Kingston 2021-03-16 19:11:00 +00:00
parent d1be0a58b4
commit 788817d249
5 changed files with 68 additions and 32 deletions

View File

@ -1,7 +1,7 @@
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { get } from "svelte/store" import { get } from "svelte/store"
import { backendUiStore, store } from "builderStore" import { backendUiStore, store } from "builderStore"
import { findComponentPath } from "./storeUtils" import { findComponent, findComponentPath } from "./storeUtils"
import { makePropSafe } from "@budibase/string-templates" import { makePropSafe } from "@budibase/string-templates"
import { TableNames } from "../constants" import { TableNames } from "../constants"
@ -69,7 +69,7 @@ export const getDatasourceForProvider = component => {
} }
// Extract datasource from component instance // Extract datasource from component instance
const validSettingTypes = ["datasource", "table", "schema"] const validSettingTypes = ["dataSource", "table", "schema"]
const datasourceSetting = def.settings.find(setting => { const datasourceSetting = def.settings.find(setting => {
return validSettingTypes.includes(setting.type) return validSettingTypes.includes(setting.type)
}) })
@ -104,21 +104,35 @@ const getContextBindings = (asset, componentId) => {
const def = store.actions.components.getDefinition(component._component) const def = store.actions.components.getDefinition(component._component)
const contextDefinition = def.dataContext const contextDefinition = def.dataContext
let schema let schema
let readablePrefix
// Forms are an edge case which do not need table schemas // Forms are an edge case which do not need table schemas
if (contextDefinition.type === "form") { if (contextDefinition.type === "form") {
schema = buildFormSchema(component) schema = buildFormSchema(component)
tableName = "Fields" readablePrefix = "Fields"
} else { } else if (contextDefinition.type === "static") {
const datasource = getDatasourceForProvider(component) schema = {}
const values = contextDefinition.values || []
values.forEach(value => {
schema[value.key] = { name: value.label, type: "string" }
})
} else if (contextDefinition.type === "schema") {
let datasource
const setting = contextDefinition.dataProviderSetting
const settingValue = component[setting]
if (settingValue) {
const providerId = settingValue.match(/{{\s*literal\s+(\S+)\s*}}/)[1]
const provider = findComponent(asset.props, providerId)
datasource = getDatasourceForProvider(provider)
}
if (!datasource) { if (!datasource) {
return return
} }
// Get schema and table for the datasource // Get schema and table for the datasource
const info = getSchemaForDatasource(datasource, isForm) const info = getSchemaForDatasource(datasource)
schema = info.schema schema = info.schema
tableName = info.table?.name readablePrefix = info.table?.name
// Add _id and _rev fields for certain types // Add _id and _rev fields for certain types
if (schema && ["table", "link"].includes(datasource.type)) { if (schema && ["table", "link"].includes(datasource.type)) {
@ -126,7 +140,7 @@ const getContextBindings = (asset, componentId) => {
schema["_rev"] = { type: "string" } schema["_rev"] = { type: "string" }
} }
} }
if (!schema || !tableName) { if (!schema) {
return return
} }
@ -135,20 +149,31 @@ const getContextBindings = (asset, componentId) => {
// Create bindable properties for each schema field // Create bindable properties for each schema field
keys.forEach(key => { keys.forEach(key => {
const fieldSchema = schema[key] const fieldSchema = schema[key]
// Replace certain bindings with a new property to help display components
// Make safe runtime binding and replace certain bindings with a
// new property to help display components
let runtimeBoundKey = key let runtimeBoundKey = key
if (fieldSchema.type === "link") { if (fieldSchema.type === "link") {
runtimeBoundKey = `${key}_text` runtimeBoundKey = `${key}_text`
} else if (fieldSchema.type === "attachment") { } else if (fieldSchema.type === "attachment") {
runtimeBoundKey = `${key}_first` runtimeBoundKey = `${key}_first`
} }
runtimeBoundKey = makePropSafe(runtimeBoundKey)
const componentId = makePropSafe(component._id)
const runtimeBinding = `${componentId}.${runtimeBoundKey}`
// Optionally use a prefix with readable bindings
let readableBinding = component._instanceName
if (readablePrefix) {
readableBinding += `.${readablePrefix}`
}
readableBinding += `.${fieldSchema.name || key}`
// Create the binding object
bindings.push({ bindings.push({
type: "context", type: "context",
runtimeBinding: `${makePropSafe(component._id)}.${makePropSafe( runtimeBinding,
runtimeBoundKey readableBinding,
)}`,
readableBinding: `${component._instanceName}.${tableName}.${key}`,
// Field schema and provider are required to construct relationship // Field schema and provider are required to construct relationship
// datasource options, based on bindable properties // datasource options, based on bindable properties
fieldSchema, fieldSchema,
@ -274,7 +299,7 @@ const buildFormSchema = component => {
if (fieldSetting && component.field) { if (fieldSetting && component.field) {
const type = fieldSetting.type.split("field/")[1] const type = fieldSetting.type.split("field/")[1]
if (type) { if (type) {
schema[component.field] = { name: component.field, type } schema[component.field] = { type }
} }
} }
component._children?.forEach(child => { component._children?.forEach(child => {

View File

@ -6,7 +6,6 @@
export let value export let value
$: path = findComponentPath($currentAsset.props, $store.selectedComponentId) $: path = findComponentPath($currentAsset.props, $store.selectedComponentId)
$: console.log(path)
$: providers = path.filter( $: providers = path.filter(
component => component =>
component._component === "@budibase/standard-components/dataprovider" component._component === "@budibase/standard-components/dataprovider"
@ -17,7 +16,9 @@
<option value="">Choose option</option> <option value="">Choose option</option>
{#if providers} {#if providers}
{#each providers as component} {#each providers as component}
<option value={component._id}>{component._instanceName}</option> <option value={`{{ literal ${component._id} }}`}>
{component._instanceName}
</option>
{/each} {/each}
{/if} {/if}
</Select> </Select>

View File

@ -88,7 +88,7 @@
{ {
"type": "dataProvider", "type": "dataProvider",
"label": "Data", "label": "Data",
"key": "dataProviderId" "key": "dataProvider"
}, },
{ {
"type": "text", "type": "text",
@ -104,7 +104,7 @@
], ],
"dataContext": { "dataContext": {
"type": "schema", "type": "schema",
"dataProviderSetting": "dataProviderId" "dataProviderSetting": "dataProvider"
} }
}, },
"search": { "search": {
@ -1490,6 +1490,23 @@
"type": "filter", "type": "filter",
"label": "Filtering", "label": "Filtering",
"key": "filter" "key": "filter"
},
{
"type": "field",
"label": "Sort Column",
"key": "sortColumn"
},
{
"type": "select",
"label": "Sort Order",
"key": "sortOrder",
"options": ["Ascending", "Descending"],
"defaultValue": "Descending"
},
{
"type": "number",
"label": "Limit",
"key": "limit"
} }
], ],
"dataContext": { "dataContext": {

View File

@ -21,13 +21,6 @@
$: filteredRows = filterRows(allRows, filter) $: filteredRows = filterRows(allRows, filter)
$: sortedRows = sortRows(filteredRows, sortColumn, sortOrder) $: sortedRows = sortRows(filteredRows, sortColumn, sortOrder)
$: rows = limitRows(sortedRows, limit) $: rows = limitRows(sortedRows, limit)
$: {
console.log(allRows)
console.log(filteredRows)
console.log(sortedRows)
console.log(rows)
}
$: actions = [ $: actions = [
{ {
type: ActionTypes.RefreshDatasource, type: ActionTypes.RefreshDatasource,
@ -46,7 +39,7 @@
loading = true loading = true
allRows = await API.fetchDatasource(dataSource) allRows = await API.fetchDatasource(dataSource)
loading = false loading = false
loaded = false loaded = true
} }
const filterRows = (rows, filter) => { const filterRows = (rows, filter) => {
@ -71,7 +64,7 @@
return rows.slice().sort((a, b) => { return rows.slice().sort((a, b) => {
const colA = a[sortColumn] const colA = a[sortColumn]
const colB = b[sortColumn] const colB = b[sortColumn]
if (sortOrder === "descending") { if (sortOrder === "Descending") {
return colA > colB ? -1 : 1 return colA > colB ? -1 : 1
} else { } else {
return colA > colB ? 1 : -1 return colA > colB ? 1 : -1

View File

@ -1,23 +1,23 @@
<script> <script>
import { getContext } from "svelte" import { getContext } from "svelte"
export let dataProviderId export let dataProvider
export let noRowsMessage export let noRowsMessage
const { API, styleable, builderStore, Provider } = getContext("sdk") const { API, styleable, builderStore, Provider } = getContext("sdk")
const component = getContext("component") const component = getContext("component")
const context = getContext("context") const context = getContext("context")
$: data = context[dataProviderId]?.rows ?? [] $: rows = dataProvider?.rows ?? []
$: loaded = context[dataProviderId]?.loaded ?? false $: loaded = dataProvider?.loaded ?? false
</script> </script>
<div use:styleable={$component.styles}> <div use:styleable={$component.styles}>
{#if data.length > 0} {#if rows.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 data as row} {#each rows as row}
<Provider data={row}> <Provider data={row}>
<slot /> <slot />
</Provider> </Provider>