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 { get } from "svelte/store"
import { backendUiStore, store } from "builderStore"
import { findComponentPath } from "./storeUtils"
import { findComponent, findComponentPath } from "./storeUtils"
import { makePropSafe } from "@budibase/string-templates"
import { TableNames } from "../constants"
@ -69,7 +69,7 @@ export const getDatasourceForProvider = component => {
}
// Extract datasource from component instance
const validSettingTypes = ["datasource", "table", "schema"]
const validSettingTypes = ["dataSource", "table", "schema"]
const datasourceSetting = def.settings.find(setting => {
return validSettingTypes.includes(setting.type)
})
@ -104,21 +104,35 @@ const getContextBindings = (asset, componentId) => {
const def = store.actions.components.getDefinition(component._component)
const contextDefinition = def.dataContext
let schema
let readablePrefix
// Forms are an edge case which do not need table schemas
if (contextDefinition.type === "form") {
schema = buildFormSchema(component)
tableName = "Fields"
} else {
const datasource = getDatasourceForProvider(component)
readablePrefix = "Fields"
} else if (contextDefinition.type === "static") {
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) {
return
}
// Get schema and table for the datasource
const info = getSchemaForDatasource(datasource, isForm)
const info = getSchemaForDatasource(datasource)
schema = info.schema
tableName = info.table?.name
readablePrefix = info.table?.name
// Add _id and _rev fields for certain types
if (schema && ["table", "link"].includes(datasource.type)) {
@ -126,7 +140,7 @@ const getContextBindings = (asset, componentId) => {
schema["_rev"] = { type: "string" }
}
}
if (!schema || !tableName) {
if (!schema) {
return
}
@ -135,20 +149,31 @@ const getContextBindings = (asset, componentId) => {
// Create bindable properties for each schema field
keys.forEach(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
if (fieldSchema.type === "link") {
runtimeBoundKey = `${key}_text`
} else if (fieldSchema.type === "attachment") {
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({
type: "context",
runtimeBinding: `${makePropSafe(component._id)}.${makePropSafe(
runtimeBoundKey
)}`,
readableBinding: `${component._instanceName}.${tableName}.${key}`,
runtimeBinding,
readableBinding,
// Field schema and provider are required to construct relationship
// datasource options, based on bindable properties
fieldSchema,
@ -274,7 +299,7 @@ const buildFormSchema = component => {
if (fieldSetting && component.field) {
const type = fieldSetting.type.split("field/")[1]
if (type) {
schema[component.field] = { name: component.field, type }
schema[component.field] = { type }
}
}
component._children?.forEach(child => {

View File

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

View File

@ -88,7 +88,7 @@
{
"type": "dataProvider",
"label": "Data",
"key": "dataProviderId"
"key": "dataProvider"
},
{
"type": "text",
@ -104,7 +104,7 @@
],
"dataContext": {
"type": "schema",
"dataProviderSetting": "dataProviderId"
"dataProviderSetting": "dataProvider"
}
},
"search": {
@ -1490,6 +1490,23 @@
"type": "filter",
"label": "Filtering",
"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": {

View File

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

View File

@ -1,23 +1,23 @@
<script>
import { getContext } from "svelte"
export let dataProviderId
export let dataProvider
export let noRowsMessage
const { API, styleable, builderStore, Provider } = getContext("sdk")
const component = getContext("component")
const context = getContext("context")
$: data = context[dataProviderId]?.rows ?? []
$: loaded = context[dataProviderId]?.loaded ?? false
$: rows = dataProvider?.rows ?? []
$: loaded = dataProvider?.loaded ?? false
</script>
<div use:styleable={$component.styles}>
{#if data.length > 0}
{#if rows.length > 0}
{#if $component.children === 0 && $builderStore.inBuilder}
<p><i class="ri-image-line" />Add some components to display.</p>
{:else}
{#each data as row}
{#each rows as row}
<Provider data={row}>
<slot />
</Provider>