164 lines
4.0 KiB
JavaScript
164 lines
4.0 KiB
JavaScript
import { store } from "./index"
|
|
|
|
/**
|
|
* Recursively searches for a specific component ID
|
|
*/
|
|
export const findComponent = (rootComponent, id) => {
|
|
return searchComponentTree(rootComponent, comp => comp._id === id)
|
|
}
|
|
|
|
/**
|
|
* Recursively searches for a specific component type
|
|
*/
|
|
export const findComponentType = (rootComponent, type) => {
|
|
return searchComponentTree(rootComponent, comp => comp._component === type)
|
|
}
|
|
|
|
/**
|
|
* Recursively searches for the parent component of a specific component ID
|
|
*/
|
|
export const findComponentParent = (rootComponent, id, parentComponent) => {
|
|
if (!rootComponent || !id) {
|
|
return null
|
|
}
|
|
if (rootComponent._id === id) {
|
|
return parentComponent
|
|
}
|
|
if (!rootComponent._children) {
|
|
return null
|
|
}
|
|
for (const child of rootComponent._children) {
|
|
const childResult = findComponentParent(child, id, rootComponent)
|
|
if (childResult) {
|
|
return childResult
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Recursively searches for a specific component ID and records the component
|
|
* path to this component
|
|
*/
|
|
export const findComponentPath = (rootComponent, id, path = []) => {
|
|
if (!rootComponent || !id) {
|
|
return []
|
|
}
|
|
if (rootComponent._id === id) {
|
|
return [...path, rootComponent]
|
|
}
|
|
if (!rootComponent._children) {
|
|
return []
|
|
}
|
|
for (const child of rootComponent._children) {
|
|
const newPath = [...path, rootComponent]
|
|
const childResult = findComponentPath(child, id, newPath)
|
|
if (childResult?.length) {
|
|
return childResult
|
|
}
|
|
}
|
|
return []
|
|
}
|
|
|
|
/**
|
|
* Recurses through the component tree and finds all components which match
|
|
* a certain selector
|
|
*/
|
|
export const findAllMatchingComponents = (rootComponent, selector) => {
|
|
if (!rootComponent || !selector) {
|
|
return []
|
|
}
|
|
let components = []
|
|
if (rootComponent._children) {
|
|
rootComponent._children.forEach(child => {
|
|
components = [
|
|
...components,
|
|
...findAllMatchingComponents(child, selector),
|
|
]
|
|
})
|
|
}
|
|
if (selector(rootComponent)) {
|
|
components.push(rootComponent)
|
|
}
|
|
return components.reverse()
|
|
}
|
|
|
|
/**
|
|
* Finds the closes parent component which matches certain criteria
|
|
*/
|
|
export const findClosestMatchingComponent = (
|
|
rootComponent,
|
|
componentId,
|
|
selector
|
|
) => {
|
|
if (!selector) {
|
|
return null
|
|
}
|
|
const componentPath = findComponentPath(rootComponent, componentId).reverse()
|
|
for (let component of componentPath) {
|
|
if (selector(component)) {
|
|
return component
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Recurses through a component tree evaluating a matching function against
|
|
* components until a match is found
|
|
*/
|
|
const searchComponentTree = (rootComponent, matchComponent) => {
|
|
if (!rootComponent || !matchComponent) {
|
|
return null
|
|
}
|
|
if (matchComponent(rootComponent)) {
|
|
return rootComponent
|
|
}
|
|
if (!rootComponent._children) {
|
|
return null
|
|
}
|
|
for (const child of rootComponent._children) {
|
|
const childResult = searchComponentTree(child, matchComponent)
|
|
if (childResult) {
|
|
return childResult
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Searches a component's definition for a setting matching a certain predicate.
|
|
* These settings are cached because they cannot change at run time.
|
|
*/
|
|
let componentSettingCache = {}
|
|
export const getComponentSettings = componentType => {
|
|
if (!componentType) {
|
|
return []
|
|
}
|
|
|
|
// Ensure whole component name is used
|
|
if (!componentType.startsWith("@budibase")) {
|
|
componentType = `@budibase/standard-components/${componentType}`
|
|
}
|
|
|
|
// Check if we have cached this type already
|
|
if (componentSettingCache[componentType]) {
|
|
return componentSettingCache[componentType]
|
|
}
|
|
|
|
// Otherwise get the settings and cache them
|
|
const def = store.actions.components.getDefinition(componentType)
|
|
let settings = []
|
|
if (def) {
|
|
settings = def.settings?.filter(setting => !setting.section) ?? []
|
|
def.settings
|
|
?.filter(setting => setting.section)
|
|
.forEach(section => {
|
|
settings = settings.concat(section.settings || [])
|
|
})
|
|
}
|
|
componentSettingCache[componentType] = settings
|
|
|
|
return settings
|
|
}
|