Types
This commit is contained in:
parent
a2d36410d6
commit
b931a24d5e
|
@ -8,28 +8,32 @@ import {
|
||||||
} from "@budibase/string-templates"
|
} from "@budibase/string-templates"
|
||||||
import { capitalise } from "@/helpers"
|
import { capitalise } from "@/helpers"
|
||||||
import { Constants } from "@budibase/frontend-core"
|
import { Constants } from "@budibase/frontend-core"
|
||||||
import { ScreenProps } from "@budibase/types"
|
import { Component, ComponentContext } from "@budibase/types"
|
||||||
|
|
||||||
const { ContextScopes } = Constants
|
const { ContextScopes } = Constants
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively searches for a specific component ID
|
* Recursively searches for a specific component ID
|
||||||
*/
|
*/
|
||||||
export const findComponent = (rootComponent: ScreenProps, id: string) => {
|
export const findComponent = (rootComponent: Component, id: string) => {
|
||||||
return searchComponentTree(rootComponent, comp => comp._id === id)
|
return searchComponentTree(rootComponent, comp => comp._id === id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively searches for a specific component type
|
* Recursively searches for a specific component type
|
||||||
*/
|
*/
|
||||||
export const findComponentType = (rootComponent, type) => {
|
export const findComponentType = (rootComponent: Component, type: string) => {
|
||||||
return searchComponentTree(rootComponent, comp => comp._component === type)
|
return searchComponentTree(rootComponent, comp => comp._component === type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively searches for the parent component of a specific component ID
|
* Recursively searches for the parent component of a specific component ID
|
||||||
*/
|
*/
|
||||||
export const findComponentParent = (rootComponent, id, parentComponent) => {
|
export const findComponentParent = (
|
||||||
|
rootComponent: Component,
|
||||||
|
id: string,
|
||||||
|
parentComponent: Component
|
||||||
|
): Component | null => {
|
||||||
if (!rootComponent || !id) {
|
if (!rootComponent || !id) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -52,7 +56,11 @@ export const findComponentParent = (rootComponent, id, parentComponent) => {
|
||||||
* Recursively searches for a specific component ID and records the component
|
* Recursively searches for a specific component ID and records the component
|
||||||
* path to this component
|
* path to this component
|
||||||
*/
|
*/
|
||||||
export const findComponentPath = (rootComponent, id, path = []) => {
|
export const findComponentPath = (
|
||||||
|
rootComponent: Component,
|
||||||
|
id: string,
|
||||||
|
path: Component[] = []
|
||||||
|
): Component[] => {
|
||||||
if (!rootComponent || !id) {
|
if (!rootComponent || !id) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -76,11 +84,14 @@ export const findComponentPath = (rootComponent, id, path = []) => {
|
||||||
* Recurses through the component tree and finds all components which match
|
* Recurses through the component tree and finds all components which match
|
||||||
* a certain selector
|
* a certain selector
|
||||||
*/
|
*/
|
||||||
export const findAllMatchingComponents = (rootComponent, selector) => {
|
export const findAllMatchingComponents = (
|
||||||
|
rootComponent: Component,
|
||||||
|
selector: (component: Component) => boolean
|
||||||
|
) => {
|
||||||
if (!rootComponent || !selector) {
|
if (!rootComponent || !selector) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
let components = []
|
let components: Component[] = []
|
||||||
if (rootComponent._children) {
|
if (rootComponent._children) {
|
||||||
rootComponent._children.forEach(child => {
|
rootComponent._children.forEach(child => {
|
||||||
components = [
|
components = [
|
||||||
|
@ -98,7 +109,7 @@ export const findAllMatchingComponents = (rootComponent, selector) => {
|
||||||
/**
|
/**
|
||||||
* Recurses through the component tree and finds all components.
|
* Recurses through the component tree and finds all components.
|
||||||
*/
|
*/
|
||||||
export const findAllComponents = rootComponent => {
|
export const findAllComponents = (rootComponent: Component) => {
|
||||||
return findAllMatchingComponents(rootComponent, () => true)
|
return findAllMatchingComponents(rootComponent, () => true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +117,9 @@ export const findAllComponents = rootComponent => {
|
||||||
* Finds the closest parent component which matches certain criteria
|
* Finds the closest parent component which matches certain criteria
|
||||||
*/
|
*/
|
||||||
export const findClosestMatchingComponent = (
|
export const findClosestMatchingComponent = (
|
||||||
rootComponent,
|
rootComponent: Component,
|
||||||
componentId,
|
componentId: string,
|
||||||
selector
|
selector: (component: Component) => boolean
|
||||||
) => {
|
) => {
|
||||||
if (!selector) {
|
if (!selector) {
|
||||||
return null
|
return null
|
||||||
|
@ -126,7 +137,10 @@ export const findClosestMatchingComponent = (
|
||||||
* Recurses through a component tree evaluating a matching function against
|
* Recurses through a component tree evaluating a matching function against
|
||||||
* components until a match is found
|
* components until a match is found
|
||||||
*/
|
*/
|
||||||
const searchComponentTree = (rootComponent, matchComponent) => {
|
const searchComponentTree = (
|
||||||
|
rootComponent: Component,
|
||||||
|
matchComponent: (component: Component) => boolean
|
||||||
|
): Component | null => {
|
||||||
if (!rootComponent || !matchComponent) {
|
if (!rootComponent || !matchComponent) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -151,15 +165,18 @@ const searchComponentTree = (rootComponent, matchComponent) => {
|
||||||
* This mutates the object in place.
|
* This mutates the object in place.
|
||||||
* @param component the component to randomise
|
* @param component the component to randomise
|
||||||
*/
|
*/
|
||||||
export const makeComponentUnique = component => {
|
export const makeComponentUnique = (component: Component) => {
|
||||||
if (!component) {
|
if (!component) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a full set of component ID replacements in this tree
|
// Generate a full set of component ID replacements in this tree
|
||||||
const idReplacements = []
|
const idReplacements: [string, string][] = []
|
||||||
const generateIdReplacements = (component, replacements) => {
|
const generateIdReplacements = (
|
||||||
const oldId = component._id
|
component: Component,
|
||||||
|
replacements: [string, string][]
|
||||||
|
) => {
|
||||||
|
const oldId = component._id!
|
||||||
const newId = Helpers.uuid()
|
const newId = Helpers.uuid()
|
||||||
replacements.push([oldId, newId])
|
replacements.push([oldId, newId])
|
||||||
component._children?.forEach(x => generateIdReplacements(x, replacements))
|
component._children?.forEach(x => generateIdReplacements(x, replacements))
|
||||||
|
@ -183,9 +200,9 @@ export const makeComponentUnique = component => {
|
||||||
let js = decodeJSBinding(sanitizedBinding)
|
let js = decodeJSBinding(sanitizedBinding)
|
||||||
if (js != null) {
|
if (js != null) {
|
||||||
// Replace ID inside JS binding
|
// Replace ID inside JS binding
|
||||||
idReplacements.forEach(([oldId, newId]) => {
|
for (const [oldId, newId] of idReplacements) {
|
||||||
js = js.replace(new RegExp(oldId, "g"), newId)
|
js = js.replace(new RegExp(oldId, "g"), newId)
|
||||||
})
|
}
|
||||||
|
|
||||||
// Create new valid JS binding
|
// Create new valid JS binding
|
||||||
let newBinding = encodeJSBinding(js)
|
let newBinding = encodeJSBinding(js)
|
||||||
|
@ -205,7 +222,7 @@ export const makeComponentUnique = component => {
|
||||||
return JSON.parse(definition)
|
return JSON.parse(definition)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getComponentText = component => {
|
export const getComponentText = (component: Component) => {
|
||||||
if (component == null) {
|
if (component == null) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -219,7 +236,7 @@ export const getComponentText = component => {
|
||||||
return capitalise(type)
|
return capitalise(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getComponentName = component => {
|
export const getComponentName = (component: Component) => {
|
||||||
if (component == null) {
|
if (component == null) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -230,9 +247,9 @@ export const getComponentName = component => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets all contexts exposed by a certain component type, including actions
|
// Gets all contexts exposed by a certain component type, including actions
|
||||||
export const getComponentContexts = component => {
|
export const getComponentContexts = (component: string) => {
|
||||||
const def = componentStore.getDefinition(component)
|
const def = componentStore.getDefinition(component)
|
||||||
let contexts = []
|
let contexts: ComponentContext[] = []
|
||||||
if (def?.context) {
|
if (def?.context) {
|
||||||
contexts = Array.isArray(def.context) ? [...def.context] : [def.context]
|
contexts = Array.isArray(def.context) ? [...def.context] : [def.context]
|
||||||
}
|
}
|
||||||
|
@ -252,9 +269,9 @@ export const getComponentContexts = component => {
|
||||||
* Recurses through the component tree and builds a tree of contexts provided
|
* Recurses through the component tree and builds a tree of contexts provided
|
||||||
* by components.
|
* by components.
|
||||||
*/
|
*/
|
||||||
export const buildContextTree = (
|
const buildContextTree = (
|
||||||
rootComponent,
|
rootComponent: Component,
|
||||||
tree = { root: [] },
|
tree: Record<string, string[]> = { root: [] },
|
||||||
currentBranch = "root"
|
currentBranch = "root"
|
||||||
) => {
|
) => {
|
||||||
// Sanity check
|
// Sanity check
|
||||||
|
@ -265,12 +282,12 @@ export const buildContextTree = (
|
||||||
// Process this component's contexts
|
// Process this component's contexts
|
||||||
const contexts = getComponentContexts(rootComponent._component)
|
const contexts = getComponentContexts(rootComponent._component)
|
||||||
if (contexts.length) {
|
if (contexts.length) {
|
||||||
tree[currentBranch].push(rootComponent._id)
|
tree[currentBranch].push(rootComponent._id!)
|
||||||
|
|
||||||
// If we provide local context, start a new branch for our children
|
// If we provide local context, start a new branch for our children
|
||||||
if (contexts.some(context => context.scope === ContextScopes.Local)) {
|
if (contexts.some(context => context.scope === ContextScopes.Local)) {
|
||||||
currentBranch = rootComponent._id
|
currentBranch = rootComponent._id!
|
||||||
tree[rootComponent._id] = []
|
tree[rootComponent._id!] = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,9 +317,9 @@ export const buildContextTreeLookupMap = rootComponent => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a flat list of ids for all descendants of a component
|
// Get a flat list of ids for all descendants of a component
|
||||||
export const getChildIdsForComponent = component => {
|
export const getChildIdsForComponent = (component: Component): string[] => {
|
||||||
return [
|
return [
|
||||||
component._id,
|
component._id!,
|
||||||
...(component?._children ?? []).map(getChildIdsForComponent).flat(1),
|
...(component?._children ?? []).map(getChildIdsForComponent).flat(1),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,10 +112,7 @@ export const EventPublishType = {
|
||||||
ENV_VAR_UPGRADE_PANEL_OPENED: "environment_variable_upgrade_panel_opened",
|
ENV_VAR_UPGRADE_PANEL_OPENED: "environment_variable_upgrade_panel_opened",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ContextScopes = {
|
export { ComponentContextScopes } from "@budibase/types"
|
||||||
Local: "local",
|
|
||||||
Global: "global",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TypeIconMap = {
|
export const TypeIconMap = {
|
||||||
[FieldType.STRING]: "Text",
|
[FieldType.STRING]: "Text",
|
||||||
|
|
|
@ -28,6 +28,8 @@ export interface ComponentDefinition {
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
}
|
}
|
||||||
|
context?: ComponentContext | ComponentContext[]
|
||||||
|
actions?: (string | any)[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DependsOnComponentSetting =
|
export type DependsOnComponentSetting =
|
||||||
|
@ -56,3 +58,16 @@ export interface ComponentSetting {
|
||||||
self: boolean
|
self: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ComponentContext {
|
||||||
|
type: ComponentContextType
|
||||||
|
scope: ComponentContextScopes
|
||||||
|
actions: any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ComponentContextType = "action"
|
||||||
|
|
||||||
|
export const enum ComponentContextScopes {
|
||||||
|
Local = "local",
|
||||||
|
Global = "global",
|
||||||
|
}
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
export type PreviewDevice = "desktop" | "tablet" | "mobile"
|
export type PreviewDevice = "desktop" | "tablet" | "mobile"
|
||||||
export type ComponentContext = Record<string, any>
|
|
||||||
|
|
Loading…
Reference in New Issue