Add button actions, simplify contexts and tidy up
This commit is contained in:
parent
199c3409c9
commit
1e857f101a
|
@ -40,13 +40,16 @@
|
||||||
|
|
||||||
$: links = bindableProperties
|
$: links = bindableProperties
|
||||||
.filter(x => x.fieldSchema?.type === "link")
|
.filter(x => x.fieldSchema?.type === "link")
|
||||||
.map(property => ({
|
.map(property => {
|
||||||
label: property.readableBinding,
|
return {
|
||||||
fieldName: property.fieldSchema.name,
|
providerId: property.instance._id,
|
||||||
name: `all_${property.fieldSchema.tableId}`,
|
label: property.readableBinding,
|
||||||
tableId: property.fieldSchema.tableId,
|
fieldName: property.fieldSchema.name,
|
||||||
type: "link",
|
name: `all_${property.fieldSchema.tableId}`,
|
||||||
}))
|
tableId: property.fieldSchema.tableId,
|
||||||
|
type: "link",
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAppId } from "../utils"
|
import { getAppId } from "../utils/getAppId"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API cache for cached request responses.
|
* API cache for cached request responses.
|
||||||
|
|
|
@ -19,9 +19,10 @@ export const fetchDatasource = async (datasource, dataContext) => {
|
||||||
} else if (type === "view") {
|
} else if (type === "view") {
|
||||||
rows = await fetchViewData(datasource)
|
rows = await fetchViewData(datasource)
|
||||||
} else if (type === "link") {
|
} else if (type === "link") {
|
||||||
|
const row = dataContext[datasource.providerId]
|
||||||
rows = await fetchRelationshipData({
|
rows = await fetchRelationshipData({
|
||||||
rowId: dataContext?._id,
|
rowId: row?._id,
|
||||||
tableId: dataContext?.tableId,
|
tableId: row?.tableId,
|
||||||
fieldName,
|
fieldName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { writable } from "svelte/store"
|
||||||
import { setContext, onMount } from "svelte"
|
import { setContext, onMount } from "svelte"
|
||||||
import Component from "./Component.svelte"
|
import Component from "./Component.svelte"
|
||||||
import SDK from "../sdk"
|
import SDK from "../sdk"
|
||||||
import { routeStore, screenStore, createDataStore } from "../store"
|
import { createDataStore, routeStore, screenStore } from "../store"
|
||||||
|
|
||||||
// Provide contexts
|
// Provide contexts
|
||||||
setContext("sdk", SDK)
|
setContext("sdk", SDK)
|
||||||
|
setContext("component", writable({}))
|
||||||
setContext("data", createDataStore())
|
setContext("data", createDataStore())
|
||||||
|
|
||||||
let loaded = false
|
let loaded = false
|
||||||
|
|
|
@ -3,69 +3,35 @@
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import * as ComponentLibrary from "@budibase/standard-components"
|
import * as ComponentLibrary from "@budibase/standard-components"
|
||||||
import Router from "./Router.svelte"
|
import Router from "./Router.svelte"
|
||||||
import { enrichDataBinding } from "../utils"
|
import { enrichProps } from "../utils/componentProps"
|
||||||
import { bindingStore } from "../store"
|
import { bindingStore } from "../store"
|
||||||
|
|
||||||
export let definition = {}
|
export let definition = {}
|
||||||
|
|
||||||
// Extracts the actual component name from the library name
|
// Get local data binding context
|
||||||
const extractComponentName = name => {
|
const dataStore = getContext("data")
|
||||||
const split = name?.split("/")
|
|
||||||
return split?.[split.length - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts valid props to pass to the real svelte component
|
// Create component context
|
||||||
const extractValidProps = component => {
|
const componentStore = writable({})
|
||||||
let props = {}
|
setContext("component", componentStore)
|
||||||
Object.entries(component)
|
|
||||||
.filter(([name]) => !name.startsWith("_"))
|
|
||||||
.forEach(([key, value]) => {
|
|
||||||
props[key] = value
|
|
||||||
})
|
|
||||||
return props
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enriches data bindings to real values based on data context
|
|
||||||
const enrichDataBindings = (dataContexts, dataBindings, props) => {
|
|
||||||
const state = {
|
|
||||||
...dataContexts,
|
|
||||||
...dataBindings,
|
|
||||||
}
|
|
||||||
let enrichedProps = {}
|
|
||||||
Object.entries(props).forEach(([key, value]) => {
|
|
||||||
enrichedProps[key] = enrichDataBinding(value, state)
|
|
||||||
})
|
|
||||||
return enrichedProps
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the component constructor for the specified component
|
|
||||||
const getComponentConstructor = name => {
|
|
||||||
return name === "screenslot" ? Router : ComponentLibrary[componentName]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract component definition info
|
// Extract component definition info
|
||||||
$: componentName = extractComponentName(definition._component)
|
$: constructor = getComponentConstructor(definition._component)
|
||||||
$: constructor = getComponentConstructor(componentName)
|
|
||||||
$: componentProps = extractValidProps(definition)
|
|
||||||
$: children = definition._children
|
$: children = definition._children
|
||||||
$: id = definition._id
|
$: id = definition._id
|
||||||
$: dataContext = getContext("data")
|
$: enrichedProps = enrichProps(definition, $dataStore, $bindingStore)
|
||||||
$: enrichedProps = enrichDataBindings(
|
|
||||||
$dataContext,
|
|
||||||
$bindingStore,
|
|
||||||
componentProps
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update component context
|
// Update component context
|
||||||
// ID is duplicated inside style so that the "styleable" helper can set
|
// ID is duplicated inside style so that the "styleable" helper can set
|
||||||
// an ID data tag for unique reference to components
|
// an ID data tag for unique reference to components
|
||||||
const componentStore = writable({})
|
$: componentStore.set({ id, styles: { ...definition._styles, id } })
|
||||||
setContext("component", componentStore)
|
|
||||||
$: componentStore.set({
|
// Gets the component constructor for the specified component
|
||||||
id,
|
const getComponentConstructor = component => {
|
||||||
styles: { ...definition._styles, id },
|
const split = component?.split("/")
|
||||||
dataContext: $dataContext.data,
|
const name = split?.[split.length - 1]
|
||||||
})
|
return name === "screenslot" ? Router : ComponentLibrary[name]
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if constructor}
|
{#if constructor}
|
||||||
|
|
|
@ -4,15 +4,11 @@
|
||||||
|
|
||||||
export let row
|
export let row
|
||||||
|
|
||||||
// Get current contexts
|
// Clone and create new data context for this component tree
|
||||||
const data = getContext("data")
|
const data = getContext("data")
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
|
|
||||||
// Clone current context to this context
|
|
||||||
const newData = createDataStore($data)
|
const newData = createDataStore($data)
|
||||||
setContext("data", newData)
|
setContext("data", newData)
|
||||||
|
|
||||||
// Add additional layer to context
|
|
||||||
$: newData.actions.addContext(row, $component.id)
|
$: newData.actions.addContext(row, $component.id)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as API from "./api"
|
import * as API from "./api"
|
||||||
import { authStore, routeStore, screenStore, bindingStore } from "./store"
|
import { authStore, routeStore, screenStore, bindingStore } from "./store"
|
||||||
import { styleable, getAppId } from "./utils"
|
import { styleable } from "./utils/styleable"
|
||||||
|
import { getAppId } from "./utils/getAppId"
|
||||||
import { link as linkable } from "svelte-spa-router"
|
import { link as linkable } from "svelte-spa-router"
|
||||||
import DataProvider from "./components/DataProvider.svelte"
|
import DataProvider from "./components/DataProvider.svelte"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as API from "../api"
|
import * as API from "../api"
|
||||||
import { getAppId } from "../utils"
|
import { getAppId } from "../utils/getAppId"
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
const createAuthStore = () => {
|
const createAuthStore = () => {
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
|
||||||
const initialValue = {
|
|
||||||
data: null,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createDataStore = existingContext => {
|
export const createDataStore = existingContext => {
|
||||||
const initial = existingContext ? cloneDeep(existingContext) : initialValue
|
const store = writable({ ...existingContext })
|
||||||
const store = writable(initial)
|
|
||||||
|
|
||||||
// Adds a context layer to the data context tree
|
// Adds a context layer to the data context tree
|
||||||
const addContext = (row, componentId) => {
|
const addContext = (row, componentId) => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
if (componentId) {
|
if (componentId) {
|
||||||
state[componentId] = row
|
state[componentId] = row
|
||||||
state.data = row
|
state[`${componentId}_draft`] = cloneDeep(row)
|
||||||
|
state.closestComponentId = componentId
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
@ -22,6 +18,9 @@ export const createDataStore = existingContext => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe: store.subscribe,
|
subscribe: store.subscribe,
|
||||||
|
update: store.update,
|
||||||
actions: { addContext },
|
actions: { addContext },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const dataStore = createDataStore()
|
||||||
|
|
|
@ -5,4 +5,4 @@ export { builderStore } from "./builder"
|
||||||
export { bindingStore } from "./binding"
|
export { bindingStore } from "./binding"
|
||||||
|
|
||||||
// Data stores are layered and duplicated, so it is not a singleton
|
// Data stores are layered and duplicated, so it is not a singleton
|
||||||
export { createDataStore } from "./data"
|
export { createDataStore, dataStore } from "./data"
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { writable, derived } from "svelte/store"
|
||||||
import { routeStore } from "./routes"
|
import { routeStore } from "./routes"
|
||||||
import { builderStore } from "./builder"
|
import { builderStore } from "./builder"
|
||||||
import * as API from "../api"
|
import * as API from "../api"
|
||||||
import { getAppId } from "../utils"
|
import { getAppId } from "../utils/getAppId"
|
||||||
|
|
||||||
const createScreenStore = () => {
|
const createScreenStore = () => {
|
||||||
const config = writable({
|
const config = writable({
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { enrichDataBinding } from "./enrichDataBinding"
|
||||||
|
import { routeStore } from "../store"
|
||||||
|
import { saveRow, deleteRow } from "../api"
|
||||||
|
|
||||||
|
const saveRowHandler = async (action, context) => {
|
||||||
|
let draft = context[`${action.parameters.contextPath}_draft`]
|
||||||
|
if (action.parameters.fields) {
|
||||||
|
Object.entries(action.parameters.fields).forEach(([key, entry]) => {
|
||||||
|
draft[key] = enrichDataBinding(entry.value, context)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await saveRow(draft)
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteRowHandler = async (action, context) => {
|
||||||
|
const { tableId, revId, rowId } = action.parameters
|
||||||
|
await deleteRow({
|
||||||
|
tableId: enrichDataBinding(tableId, context),
|
||||||
|
rowId: enrichDataBinding(rowId, context),
|
||||||
|
revId: enrichDataBinding(revId, context),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigationHandler = action => {
|
||||||
|
routeStore.actions.navigate(action.parameters.url)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlerMap = {
|
||||||
|
["Save Row"]: saveRowHandler,
|
||||||
|
["Delete Row"]: deleteRowHandler,
|
||||||
|
["Navigate To"]: navigationHandler,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an array of actions and returns a function which will execute the
|
||||||
|
* actions in the current context.
|
||||||
|
*/
|
||||||
|
export const enrichButtonActions = (actions, context) => {
|
||||||
|
const handlers = actions.map(def => handlerMap[def["##eventHandlerType"]])
|
||||||
|
return async () => {
|
||||||
|
for (let i = 0; i < handlers.length; i++) {
|
||||||
|
await handlers[i](actions[i], context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { enrichDataBindings } from "./enrichDataBinding"
|
||||||
|
import { enrichButtonActions } from "./buttonActions"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enriches component props.
|
||||||
|
* Data bindings are enriched, and button actions are enriched.
|
||||||
|
*/
|
||||||
|
export const enrichProps = (props, dataContexts, dataBindings) => {
|
||||||
|
// Exclude all private props that start with an underscore
|
||||||
|
let validProps = {}
|
||||||
|
Object.entries(props)
|
||||||
|
.filter(([name]) => !name.startsWith("_"))
|
||||||
|
.forEach(([key, value]) => {
|
||||||
|
validProps[key] = value
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create context of all bindings and data contexts
|
||||||
|
// Duplicate the closest context as "data" which the builder requires
|
||||||
|
const context = {
|
||||||
|
...dataContexts,
|
||||||
|
...dataBindings,
|
||||||
|
data: dataContexts[dataContexts.closestComponentId],
|
||||||
|
data_draft: dataContexts[`${dataContexts.closestComponentId}_draft`],
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enrich all data bindings in top level props
|
||||||
|
let enrichedProps = enrichDataBindings(validProps, context)
|
||||||
|
|
||||||
|
// Enrich button actions if they exist
|
||||||
|
if (props._component.endsWith("/button") && enrichedProps.onClick) {
|
||||||
|
enrichedProps.onClick = enrichButtonActions(enrichedProps.onClick, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
return enrichedProps
|
||||||
|
}
|
|
@ -33,3 +33,14 @@ export const enrichDataBinding = (input, context) => {
|
||||||
}
|
}
|
||||||
return mustache.render(input, context)
|
return mustache.render(input, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enriches each prop in a props object
|
||||||
|
*/
|
||||||
|
export const enrichDataBindings = (props, context) => {
|
||||||
|
let enrichedProps = {}
|
||||||
|
Object.entries(props).forEach(([key, value]) => {
|
||||||
|
enrichedProps[key] = enrichDataBinding(value, context)
|
||||||
|
})
|
||||||
|
return enrichedProps
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export { getAppId } from "./getAppId"
|
|
||||||
export { styleable } from "./styleable"
|
|
||||||
export { enrichDataBinding } from "./enrichDataBinding"
|
|
|
@ -7,12 +7,14 @@
|
||||||
export let className = "default"
|
export let className = "default"
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let text
|
export let text
|
||||||
|
export let onClick
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="default"
|
class="default"
|
||||||
disabled={disabled || false}
|
disabled={disabled || false}
|
||||||
use:styleable={$component.styles}>
|
use:styleable={$component.styles}
|
||||||
|
on:click={onClick}>
|
||||||
{text}
|
{text}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
import LinkedRowSelector from "./LinkedRowSelector.svelte"
|
import LinkedRowSelector from "./LinkedRowSelector.svelte"
|
||||||
import { capitalise } from "./helpers"
|
import { capitalise } from "./helpers"
|
||||||
|
|
||||||
const { styleable, screenStore, API } = getContext("sdk")
|
const { styleable, API } = getContext("sdk")
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
|
const data = getContext("data")
|
||||||
|
|
||||||
export let wide = false
|
export let wide = false
|
||||||
|
|
||||||
|
@ -14,14 +15,17 @@
|
||||||
let schema
|
let schema
|
||||||
let fields = []
|
let fields = []
|
||||||
|
|
||||||
$: getContextDetails($component.dataContext)
|
// Fetch info about the closest data context
|
||||||
|
$: getFormData($data[$data.closestComponentId])
|
||||||
|
|
||||||
const getContextDetails = async dataContext => {
|
const getFormData = async context => {
|
||||||
if (dataContext) {
|
if (context) {
|
||||||
row = dataContext
|
const tableDefinition = await API.fetchTableDefinition(context.tableId)
|
||||||
const tableDefinition = await API.fetchTableDefinition(row.tableId)
|
|
||||||
schema = tableDefinition.schema
|
schema = tableDefinition.schema
|
||||||
fields = Object.keys(schema)
|
fields = Object.keys(schema)
|
||||||
|
|
||||||
|
// Use the draft version for editing
|
||||||
|
row = $data[`${$data.closestComponentId}_draft`]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
const { API, styleable, DataProvider } = getContext("sdk")
|
const { API, styleable, DataProvider } = getContext("sdk")
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
|
const data = getContext("data")
|
||||||
|
|
||||||
export let datasource = []
|
export let datasource = []
|
||||||
|
|
||||||
|
@ -11,7 +12,7 @@
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (!isEmpty(datasource)) {
|
if (!isEmpty(datasource)) {
|
||||||
rows = await API.fetchDatasource(datasource, $component.dataContext)
|
rows = await API.fetchDatasource(datasource, $data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
import { isEmpty } from "lodash/fp"
|
import { isEmpty } from "lodash/fp"
|
||||||
|
|
||||||
const { API } = getContext("sdk")
|
const { API } = getContext("sdk")
|
||||||
const component = getContext("component")
|
|
||||||
|
|
||||||
export let title
|
export let title
|
||||||
export let datasource
|
export let datasource
|
||||||
|
@ -35,7 +34,7 @@
|
||||||
|
|
||||||
// Fetch, filter and sort data
|
// Fetch, filter and sort data
|
||||||
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
||||||
const result = await API.fetchDatasource(datasource, $component.dataContext)
|
const result = await API.fetchDatasource(datasource)
|
||||||
const reducer = row => (valid, column) => valid && row[column] != null
|
const reducer = row => (valid, column) => valid && row[column] != null
|
||||||
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
||||||
const data = result
|
const data = result
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
import { isEmpty } from "lodash/fp"
|
import { isEmpty } from "lodash/fp"
|
||||||
|
|
||||||
const { API } = getContext("sdk")
|
const { API } = getContext("sdk")
|
||||||
const component = getContext("component")
|
|
||||||
|
|
||||||
export let title
|
export let title
|
||||||
export let datasource
|
export let datasource
|
||||||
|
@ -33,7 +32,7 @@
|
||||||
|
|
||||||
// Fetch, filter and sort data
|
// Fetch, filter and sort data
|
||||||
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
||||||
const result = await API.fetchDatasource(datasource, $component.dataContext)
|
const result = await API.fetchDatasource(datasource)
|
||||||
const reducer = row => (valid, column) => valid && row[column] != null
|
const reducer = row => (valid, column) => valid && row[column] != null
|
||||||
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
||||||
const data = result
|
const data = result
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
import { isEmpty } from "lodash/fp"
|
import { isEmpty } from "lodash/fp"
|
||||||
|
|
||||||
const { API } = getContext("sdk")
|
const { API } = getContext("sdk")
|
||||||
const component = getContext("component")
|
|
||||||
|
|
||||||
// Common props
|
// Common props
|
||||||
export let title
|
export let title
|
||||||
|
@ -41,7 +40,7 @@
|
||||||
|
|
||||||
// Fetch, filter and sort data
|
// Fetch, filter and sort data
|
||||||
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
||||||
const result = await API.fetchDatasource(datasource, $component.dataContext)
|
const result = await API.fetchDatasource(datasource)
|
||||||
const reducer = row => (valid, column) => valid && row[column] != null
|
const reducer = row => (valid, column) => valid && row[column] != null
|
||||||
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
||||||
const data = result
|
const data = result
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
import { isEmpty } from "lodash/fp"
|
import { isEmpty } from "lodash/fp"
|
||||||
|
|
||||||
const { API } = getContext("sdk")
|
const { API } = getContext("sdk")
|
||||||
const component = getContext("component")
|
|
||||||
|
|
||||||
export let title
|
export let title
|
||||||
export let datasource
|
export let datasource
|
||||||
|
@ -31,7 +30,7 @@
|
||||||
|
|
||||||
// Fetch, filter and sort data
|
// Fetch, filter and sort data
|
||||||
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
|
||||||
const result = await API.fetchDatasource(datasource, $component.dataContext)
|
const result = await API.fetchDatasource(datasource)
|
||||||
const data = result
|
const data = result
|
||||||
.filter(row => row[labelColumn] != null && row[valueColumn] != null)
|
.filter(row => row[labelColumn] != null && row[valueColumn] != null)
|
||||||
.slice(0, 20)
|
.slice(0, 20)
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (!isEmpty(datasource)) {
|
if (!isEmpty(datasource)) {
|
||||||
data = await API.fetchDatasource(datasource, $component.dataContext)
|
data = await API.fetchDatasource(datasource)
|
||||||
let schema
|
let schema
|
||||||
|
|
||||||
// Get schema for datasource
|
// Get schema for datasource
|
||||||
|
|
Loading…
Reference in New Issue