From 4ea8b60b3b5961429b6a6d0874624261a4ce3fc1 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 30 Jan 2025 12:48:59 +0100 Subject: [PATCH 1/4] Renames --- packages/builder/src/stores/builder/components.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index 90e1abfecf..043c2da275 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -452,7 +452,7 @@ export class ComponentStore extends BudiStore { * @returns */ createInstance( - componentName: string, + componentType: string, presetProps: any, parent: any ): Component | null { @@ -461,11 +461,13 @@ export class ComponentStore extends BudiStore { throw "A valid screen must be selected" } - const definition = this.getDefinition(componentName) + const definition = this.getDefinition(componentType) if (!definition) { return null } + let componentName = `New ${definition.friendlyName || definition.name}` + // Generate basic component structure let instance: Component = { _id: Helpers.uuid(), @@ -475,7 +477,7 @@ export class ComponentStore extends BudiStore { hover: {}, active: {}, }, - _instanceName: `New ${definition.friendlyName || definition.name}`, + _instanceName: componentName, ...presetProps, } @@ -500,7 +502,7 @@ export class ComponentStore extends BudiStore { } // Add step name to form steps - if (componentName.endsWith("/formstep")) { + if (componentType.endsWith("/formstep")) { const parentForm = findClosestMatchingComponent( screen.props, get(selectedComponent)?._id, @@ -529,14 +531,14 @@ export class ComponentStore extends BudiStore { * @returns */ async create( - componentName: string, + componentType: string, presetProps: any, parent: Component, index: number ) { const state = get(this.store) const componentInstance = this.createInstance( - componentName, + componentType, presetProps, parent ) From b7ce306e6a0949fb4f34c7e15bccb2b7a1f3c00f Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 30 Jan 2025 16:30:55 +0100 Subject: [PATCH 2/4] Add counter --- .../builder/src/stores/builder/components.ts | 9 +++++++++ packages/builder/src/stores/builder/index.js | 3 ++- .../src/stores/builder/screenComponent.ts | 16 +++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index 043c2da275..7aedf05438 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -20,6 +20,7 @@ import { previewStore, tables, componentTreeNodesStore, + screenComponents, } from "@/stores/builder" import { buildFormSchema, getSchemaForDatasource } from "@/dataBinding" import { @@ -467,6 +468,14 @@ export class ComponentStore extends BudiStore { } let componentName = `New ${definition.friendlyName || definition.name}` + const $screenComponents = get(screenComponents) + + const sameNameCount = $screenComponents.filter(c => + new RegExp(`^${componentName}( \\d*)?$`).test(c._instanceName) + ).length + if (sameNameCount) { + componentName = `${componentName} ${sameNameCount + 1}` + } // Generate basic component structure let instance: Component = { diff --git a/packages/builder/src/stores/builder/index.js b/packages/builder/src/stores/builder/index.js index 54c1aa39a2..7dd7f67828 100644 --- a/packages/builder/src/stores/builder/index.js +++ b/packages/builder/src/stores/builder/index.js @@ -16,7 +16,7 @@ import { userStore, userSelectedResourceMap, isOnlyUser } from "./users.js" import { deploymentStore } from "./deployments.js" import { contextMenuStore } from "./contextMenu.js" import { snippets } from "./snippets" -import { screenComponentErrors } from "./screenComponent" +import { screenComponents, screenComponentErrors } from "./screenComponent" // Backend import { tables } from "./tables" @@ -68,6 +68,7 @@ export { snippets, rowActions, appPublished, + screenComponents, screenComponentErrors, } diff --git a/packages/builder/src/stores/builder/screenComponent.ts b/packages/builder/src/stores/builder/screenComponent.ts index 226d233090..56e9d311a4 100644 --- a/packages/builder/src/stores/builder/screenComponent.ts +++ b/packages/builder/src/stores/builder/screenComponent.ts @@ -3,11 +3,12 @@ import { tables } from "./tables" import { selectedScreen } from "./screens" import { viewsV2 } from "./viewsV2" import { findComponentsBySettingsType } from "@/helpers/screen" -import { UIDatasourceType, Screen } from "@budibase/types" +import { UIDatasourceType, Screen, Component } from "@budibase/types" import { queries } from "./queries" import { views } from "./views" import { bindings, featureFlag } from "@/helpers" import { getBindableProperties } from "@/dataBinding" +import { findAllComponents } from "@/helpers/components" function reduceBy( key: TKey, @@ -111,3 +112,16 @@ export const screenComponentErrors = derived( return getInvalidDatasources($selectedScreen, datasources) } ) + +export const screenComponents = derived( + [selectedScreen], + ([$selectedScreen]) => { + if (!$selectedScreen) { + return [] + } + const allComponents = findAllComponents( + $selectedScreen.props + ) as Component[] + return allComponents + } +) From 6f2d279f0e48c0c3557dca806ff715036b22bb33 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 30 Jan 2025 16:47:04 +0100 Subject: [PATCH 3/4] Use existing utils --- packages/builder/src/helpers/duplicate.ts | 6 ++++-- .../builder/src/stores/builder/components.ts | 18 +++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/builder/src/helpers/duplicate.ts b/packages/builder/src/helpers/duplicate.ts index b4740b3e52..eb705c6525 100644 --- a/packages/builder/src/helpers/duplicate.ts +++ b/packages/builder/src/helpers/duplicate.ts @@ -76,13 +76,15 @@ export const getSequentialName = ( { getName, numberFirstItem, + separator = "", }: { getName?: (item: T) => string numberFirstItem?: boolean + separator?: string } = {} ) => { if (!prefix?.length) { - return null + return "" } const trimmedPrefix = prefix.trim() const firstName = numberFirstItem ? `${prefix}1` : trimmedPrefix @@ -107,5 +109,5 @@ export const getSequentialName = ( max = num } }) - return max === 0 ? firstName : `${prefix}${max + 1}` + return max === 0 ? firstName : `${prefix}${separator}${max + 1}` } diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index 7aedf05438..6693cbf4dc 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -38,6 +38,7 @@ import { Table, } from "@budibase/types" import { utils } from "@budibase/shared-core" +import { getSequentialName } from "@/helpers/duplicate" interface Component extends ComponentType { _id: string @@ -467,15 +468,14 @@ export class ComponentStore extends BudiStore { return null } - let componentName = `New ${definition.friendlyName || definition.name}` - const $screenComponents = get(screenComponents) - - const sameNameCount = $screenComponents.filter(c => - new RegExp(`^${componentName}( \\d*)?$`).test(c._instanceName) - ).length - if (sameNameCount) { - componentName = `${componentName} ${sameNameCount + 1}` - } + const componentName = getSequentialName( + get(screenComponents), + `New ${definition.friendlyName || definition.name}`, + { + getName: c => c._instanceName, + separator: " ", + } + ) // Generate basic component structure let instance: Component = { From 2f4e798cf592d12681371d005b49c3c0279c3b20 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 30 Jan 2025 16:57:48 +0100 Subject: [PATCH 4/4] Fix test --- packages/builder/src/helpers/tests/duplicate.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/helpers/tests/duplicate.test.ts b/packages/builder/src/helpers/tests/duplicate.test.ts index 131e76a6c2..5e956d7b1c 100644 --- a/packages/builder/src/helpers/tests/duplicate.test.ts +++ b/packages/builder/src/helpers/tests/duplicate.test.ts @@ -49,7 +49,7 @@ describe("getSequentialName", () => { it("handles nullish prefix", async () => { const name = getSequentialName([], null) - expect(name).toBe(null) + expect(name).toBe("") }) it("handles just the prefix", async () => {