Update bindable properties to handle new data provider
This commit is contained in:
parent
d1be0a58b4
commit
788817d249
|
@ -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 => {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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": {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue