diff --git a/packages/builder/src/helpers/screen.ts b/packages/builder/src/helpers/screen.ts index e9a478d059..24988c2195 100644 --- a/packages/builder/src/helpers/screen.ts +++ b/packages/builder/src/helpers/screen.ts @@ -38,8 +38,11 @@ export function findComponentsBySettingsType( return result } -export function getManifestDefinition(component: Component) { - const componentType = component._component.split("/").slice(-1)[0] +export function getManifestDefinition(component: Component | string) { + const componentType = + typeof component === "string" + ? component + : component._component.split("/").slice(-1)[0] const definition = clientManifest[componentType as keyof typeof clientManifest] return definition diff --git a/packages/builder/src/stores/builder/screenComponent.ts b/packages/builder/src/stores/builder/screenComponent.ts index 841607e835..a94c2295df 100644 --- a/packages/builder/src/stores/builder/screenComponent.ts +++ b/packages/builder/src/stores/builder/screenComponent.ts @@ -65,6 +65,7 @@ export const screenComponentErrors = derived( const errors = { ...getInvalidDatasources($selectedScreen, datasources), + ...getMissingAncestors($selectedScreen), ...getMissingRequiredSettings($selectedScreen), } return errors @@ -182,3 +183,37 @@ function getMissingRequiredSettings(screen: Screen) { return result } + +const BudibasePrefix = "@budibase/standard-components/" +function getMissingAncestors(screen: Screen) { + const allComponents = getAllComponentsInScreen(screen) + const result: Record = {} + for (const component of allComponents) { + const definition = getManifestDefinition(component) + if (!("requiredAncestors" in definition)) { + continue + } + + const missingAncestors = definition.requiredAncestors.filter( + ancestor => !component.ancestors?.includes(`${BudibasePrefix}${ancestor}`) + ) + + if (missingAncestors.length) { + const pluralise = (name: string) => { + return name.endsWith("s") ? `${name}'` : `${name}s` + } + + const getAncestorName = (name: string) => { + const definition: any = getManifestDefinition(name) + return definition.name + } + + result[component._id!] = missingAncestors.map((s: any) => ({ + key: s.key, + message: `${pluralise(component._instanceName)} need to be inside a +${getAncestorName(s)}`, + })) + } + } + return result +}