mirror of https://github.com/Budibase/budibase.git
17 changed files with 415 additions and 542 deletions
@ -1,4 +1,4 @@ |
|||
packages/builder/src/userInterface/CurrentItemPreview.svelte |
|||
packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte |
|||
public |
|||
dist |
|||
packages/server/builder |
|||
|
|||
@ -0,0 +1,97 @@ |
|||
import { get } from "svelte/store" |
|||
import { backendUiStore, store } from "builderStore" |
|||
import { findAllMatchingComponents, findComponentPath } from "./storeUtils" |
|||
|
|||
/** |
|||
* Gets all bindable data context fields and instance fields. |
|||
*/ |
|||
export const getBindableProperties = (rootComponent, componentId) => { |
|||
const bindableContexts = getBindableContexts(rootComponent, componentId) |
|||
const bindableComponents = getBindableComponents(rootComponent) |
|||
return [...bindableContexts, ...bindableComponents] |
|||
} |
|||
|
|||
/** |
|||
* Gets all bindable data contexts. These are fields of schemas of data contexts |
|||
* provided by data provider components, such as lists or row detail components. |
|||
*/ |
|||
export const getBindableContexts = (rootComponent, componentId) => { |
|||
if (!rootComponent || !componentId) { |
|||
return [] |
|||
} |
|||
|
|||
// Get the component tree leading up to this component
|
|||
const path = findComponentPath(rootComponent, componentId) |
|||
path.pop() |
|||
|
|||
// Extract any components which provide data contexts
|
|||
const dataProviders = path.filter(component => { |
|||
const def = store.actions.components.getDefinition(component._component) |
|||
return def?.dataProvider |
|||
}) |
|||
|
|||
let contexts = [] |
|||
dataProviders.forEach(provider => { |
|||
if (!provider.datasource) { |
|||
return |
|||
} |
|||
const { schema, table } = getSchemaForDatasource(provider.datasource) |
|||
Object.entries(schema).forEach(([key, schema]) => { |
|||
// Replace certain bindings with a new property to help display components
|
|||
let runtimeBoundKey = key |
|||
if (schema.type === "link") { |
|||
runtimeBoundKey = `${key}_count` |
|||
} else if (schema.type === "attachment") { |
|||
runtimeBoundKey = `${key}_first` |
|||
} |
|||
|
|||
contexts.push({ |
|||
type: "context", |
|||
runtimeBinding: `${provider._id}.${runtimeBoundKey}`, |
|||
readableBinding: `${provider._instanceName}.${table.name}.${key}`, |
|||
fieldSchema: schema, |
|||
providerId: provider._id, |
|||
}) |
|||
}) |
|||
}) |
|||
return contexts |
|||
} |
|||
|
|||
/** |
|||
* Gets all bindable components. These are form components which allow their |
|||
* values to be bound to. |
|||
*/ |
|||
export const getBindableComponents = rootComponent => { |
|||
if (!rootComponent) { |
|||
return [] |
|||
} |
|||
const componentSelector = component => { |
|||
const type = component._component |
|||
const definition = store.actions.components.getDefinition(type) |
|||
return definition.bindable |
|||
} |
|||
const components = findAllMatchingComponents(rootComponent, componentSelector) |
|||
console.log(components) |
|||
|
|||
return [] |
|||
} |
|||
|
|||
/** |
|||
* Gets a schema for a datasource object. |
|||
*/ |
|||
const getSchemaForDatasource = datasource => { |
|||
const tables = get(backendUiStore).tables |
|||
const { type } = datasource |
|||
const table = tables.find(table => table._id === datasource.tableId) |
|||
let schema = {} |
|||
if (table) { |
|||
if (type === "table") { |
|||
schema = table.schema ?? {} |
|||
} else if (type === "view") { |
|||
schema = table.views?.[datasource.name]?.schema ?? {} |
|||
} else if (type === "link") { |
|||
schema = table.schema ?? {} |
|||
} |
|||
} |
|||
return { schema, table } |
|||
} |
|||
@ -1,48 +0,0 @@ |
|||
import { walkProps } from "./storeUtils" |
|||
import { get_capitalised_name } from "../helpers" |
|||
import { get } from "svelte/store" |
|||
import { allScreens } from "builderStore" |
|||
import { FrontendTypes } from "../constants" |
|||
import { currentAsset } from "." |
|||
|
|||
export default function(component, state) { |
|||
const capitalised = get_capitalised_name( |
|||
component.name || component._component |
|||
) |
|||
|
|||
const matchingComponents = [] |
|||
|
|||
const findMatches = props => { |
|||
walkProps(props, c => { |
|||
const thisInstanceName = get_capitalised_name(c._instanceName) |
|||
if ((thisInstanceName || "").startsWith(capitalised)) { |
|||
matchingComponents.push(thisInstanceName) |
|||
} |
|||
}) |
|||
} |
|||
|
|||
// check layouts first
|
|||
for (let layout of state.layouts) { |
|||
findMatches(layout.props) |
|||
} |
|||
|
|||
// if viewing screen, check current screen for duplicate
|
|||
if (state.currentFrontEndType === FrontendTypes.SCREEN) { |
|||
findMatches(get(currentAsset).props) |
|||
} else { |
|||
// viewing a layout - need to find against all screens
|
|||
for (let screen of get(allScreens)) { |
|||
findMatches(screen.props) |
|||
} |
|||
} |
|||
|
|||
let index = 1 |
|||
let name |
|||
while (!name) { |
|||
const tryName = `${capitalised || "Copy"} ${index}` |
|||
if (!matchingComponents.includes(tryName)) name = tryName |
|||
index++ |
|||
} |
|||
|
|||
return name |
|||
} |
|||
@ -1,12 +1,32 @@ |
|||
[ |
|||
"container", |
|||
"grid", |
|||
"list", |
|||
{ |
|||
"name": "Category", |
|||
"name": "Cards", |
|||
"icon": "ri-file-edit-line", |
|||
"children": [ |
|||
"container" |
|||
"card", |
|||
"stackedlist" |
|||
] |
|||
}, |
|||
"grid", |
|||
"screenslot", |
|||
"button" |
|||
{ |
|||
"name": "Forms", |
|||
"icon": "ri-file-edit-line", |
|||
"children": [ |
|||
"form", |
|||
"input", |
|||
"richtext", |
|||
"datepicker" |
|||
] |
|||
}, |
|||
"button", |
|||
"text", |
|||
{ |
|||
"name": "Other", |
|||
"icon": "ri-file-edit-line", |
|||
"children": [ |
|||
"screenslot" |
|||
] |
|||
} |
|||
] |
|||
Loading…
Reference in new issue