From 73d3ce2038c4086b99e4494b6d6caf6de7faa6ad Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 11:01:09 +0000 Subject: [PATCH 01/64] Initial work on support dragging new components on to grid screens and typing improvements for client --- .../new/_components/NewComponentPanel.svelte | 12 +- packages/builder/src/stores/builder/app.ts | 6 +- .../builder/src/stores/builder/components.ts | 82 +------- .../builder/src/stores/builder/navigation.ts | 4 +- .../builder/src/stores/builder/preview.ts | 17 +- packages/client/package.json | 2 +- .../client/src/components/ClientApp.svelte | 2 + .../preview/GridNewComponentDNDHandler.svelte | 166 +++++++++++++++ packages/client/src/index.d.ts | 5 - packages/client/src/index.js | 138 ------------- packages/client/src/index.ts | 195 +++++++++++++++++- packages/client/src/stores/dnd.js | 11 +- packages/client/src/stores/index.js | 2 +- packages/client/src/stores/screens.js | 4 + packages/client/vite.config.mjs | 10 +- packages/types/src/ui/components/index.ts | 10 + 16 files changed, 430 insertions(+), 236 deletions(-) create mode 100644 packages/client/src/components/preview/GridNewComponentDNDHandler.svelte delete mode 100644 packages/client/src/index.d.ts delete mode 100644 packages/client/src/index.js diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index aa0b26f6b7..784642787b 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -13,6 +13,11 @@ import { fly } from "svelte/transition" import { findComponentPath } from "@/helpers/components" + // Smallest possible 1x1 transparent GIF + const ghost = new Image(1, 1) + ghost.src = + "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" + let searchString let searchRef let selectedIndex @@ -217,7 +222,8 @@ } }) - const onDragStart = component => { + const onDragStart = (e, component) => { + e.dataTransfer.setDragImage(ghost, 0, 0) previewStore.startDrag(component) } @@ -250,7 +256,7 @@ {#each category.children as component}
onDragStart(component.component)} + on:dragstart={e => onDragStart(e, component.component)} on:dragend={onDragEnd} class="component" class:selected={selectedIndex === orderMap[component.component]} @@ -308,7 +314,7 @@ } .component:hover { background: var(--spectrum-global-color-gray-300); - cursor: pointer; + cursor: grab; } .component :global(.spectrum-Body) { line-height: 1.2 !important; diff --git a/packages/builder/src/stores/builder/app.ts b/packages/builder/src/stores/builder/app.ts index 3c8ed4afc1..abebb5d9f1 100644 --- a/packages/builder/src/stores/builder/app.ts +++ b/packages/builder/src/stores/builder/app.ts @@ -39,7 +39,7 @@ interface AppMetaState { appInstance: { _id: string } | null initialised: boolean hasAppPackage: boolean - usedPlugins: Plugin[] | null + usedPlugins: Plugin[] automations: AutomationSettings routes: { [key: string]: any } version?: string @@ -76,7 +76,7 @@ export const INITIAL_APP_META_STATE: AppMetaState = { appInstance: null, initialised: false, hasAppPackage: false, - usedPlugins: null, + usedPlugins: [], automations: {}, routes: {}, } @@ -109,7 +109,7 @@ export class AppMetaStore extends BudiStore { appInstance: app.instance, revertableVersion: app.revertableVersion, upgradableVersion: app.upgradableVersion, - usedPlugins: app.usedPlugins || null, + usedPlugins: app.usedPlugins || [], icon: app.icon, features: { ...INITIAL_APP_META_STATE.features, diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index a8f52e2660..ad221cc67d 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -139,10 +139,6 @@ export class ComponentStore extends BudiStore { /** * Retrieve the component definition object - * @param {string} componentType - * @example - * '@budibase/standard-components/container' - * @returns {object} */ getDefinition(componentType: string) { if (!componentType) { @@ -151,10 +147,6 @@ export class ComponentStore extends BudiStore { return get(this.store).components[componentType] } - /** - * - * @returns {object} - */ getDefaultDatasource() { // Ignore users table const validTables = get(tables).list.filter(x => x._id !== "ta_users") @@ -188,8 +180,6 @@ export class ComponentStore extends BudiStore { /** * Takes an enriched component instance and applies any required migration * logic - * @param {object} enrichedComponent - * @returns {object} migrated Component */ migrateSettings(enrichedComponent: Component) { const componentPrefix = "@budibase/standard-components" @@ -230,22 +220,15 @@ export class ComponentStore extends BudiStore { for (let setting of filterableTypes || []) { const isLegacy = Array.isArray(enrichedComponent[setting.key]) if (isLegacy) { - const processedSetting = utils.processSearchFilters( + enrichedComponent[setting.key] = utils.processSearchFilters( enrichedComponent[setting.key] ) - enrichedComponent[setting.key] = processedSetting migrated = true } } return migrated } - /** - * - * @param {object} component - * @param {object} opts - * @returns - */ enrichEmptySettings( component: Component, opts: { screen?: Screen; parent?: Component; useDefaultValues?: boolean } @@ -427,17 +410,10 @@ export class ComponentStore extends BudiStore { } } - /** - * - * @param {string} componentName - * @param {object} presetProps - * @param {object} parent - * @returns - */ createInstance( componentType: string, - presetProps: any, - parent: any + presetProps?: Record, + parent?: Component ): Component | null { const screen = get(selectedScreen) if (!screen) { @@ -463,7 +439,7 @@ export class ComponentStore extends BudiStore { _id: Helpers.uuid(), _component: definition.component, _styles: { - normal: {}, + normal: { ...presetProps?._styles?.normal }, hover: {}, active: {}, }, @@ -512,19 +488,11 @@ export class ComponentStore extends BudiStore { } } - /** - * - * @param {string} componentName - * @param {object} presetProps - * @param {object} parent - * @param {number} index - * @returns - */ async create( componentType: string, - presetProps: any, - parent: Component, - index: number + presetProps?: Record, + parent?: Component, + index?: number ) { const state = get(this.store) const componentInstance = this.createInstance( @@ -611,13 +579,6 @@ export class ComponentStore extends BudiStore { return componentInstance } - /** - * - * @param {function} patchFn - * @param {string} componentId - * @param {string} screenId - * @returns - */ async patch( patchFn: (component: Component, screen: Screen) => any, componentId?: string, @@ -652,11 +613,6 @@ export class ComponentStore extends BudiStore { await screenStore.patch(patchScreen, screenId) } - /** - * - * @param {object} component - * @returns - */ async delete(component: Component) { if (!component) { return @@ -737,13 +693,6 @@ export class ComponentStore extends BudiStore { }) } - /** - * - * @param {object} targetComponent - * @param {string} mode - * @param {object} targetScreen - * @returns - */ async paste( targetComponent: Component, mode: string, @@ -1101,6 +1050,7 @@ export class ComponentStore extends BudiStore { async updateStyles(styles: Record, id: string) { const patchFn = (component: Component) => { + delete component._placeholder component._styles.normal = { ...component._styles.normal, ...styles, @@ -1231,7 +1181,7 @@ export class ComponentStore extends BudiStore { } // Create new parent instance - const newParentDefinition = this.createInstance(parentType, null, parent) + const newParentDefinition = this.createInstance(parentType) if (!newParentDefinition) { return } @@ -1267,10 +1217,6 @@ export class ComponentStore extends BudiStore { /** * Check if the components settings have been cached - * @param {string} componentType - * @example - * '@budibase/standard-components/container' - * @returns {boolean} */ isCached(componentType: string) { const settings = get(this.store).settingsCache @@ -1279,11 +1225,6 @@ export class ComponentStore extends BudiStore { /** * Cache component settings - * @param {string} componentType - * @param {object} definition - * @example - * '@budibase/standard-components/container' - * @returns {array} the settings */ cacheSettings(componentType: string, definition: ComponentDefinition | null) { let settings: ComponentSetting[] = [] @@ -1313,12 +1254,7 @@ export class ComponentStore extends BudiStore { /** * Retrieve an array of the component settings. * These settings are cached because they cannot change at run time. - * * Searches a component's definition for a setting matching a certain predicate. - * @param {string} componentType - * @example - * '@budibase/standard-components/container' - * @returns {Array} */ getComponentSettings(componentType: string) { if (!componentType) { diff --git a/packages/builder/src/stores/builder/navigation.ts b/packages/builder/src/stores/builder/navigation.ts index 1574efee2a..1ef019a11c 100644 --- a/packages/builder/src/stores/builder/navigation.ts +++ b/packages/builder/src/stores/builder/navigation.ts @@ -4,15 +4,13 @@ import { appStore } from "@/stores/builder" import { BudiStore } from "../BudiStore" import { AppNavigation, AppNavigationLink, UIObject } from "@budibase/types" -interface BuilderNavigationStore extends AppNavigation {} - export const INITIAL_NAVIGATION_STATE = { navigation: "Top", links: [], textAlign: "Left", } -export class NavigationStore extends BudiStore { +export class NavigationStore extends BudiStore { constructor() { super(INITIAL_NAVIGATION_STATE) } diff --git a/packages/builder/src/stores/builder/preview.ts b/packages/builder/src/stores/builder/preview.ts index 87b2b9355e..9aeaf99346 100644 --- a/packages/builder/src/stores/builder/preview.ts +++ b/packages/builder/src/stores/builder/preview.ts @@ -1,5 +1,7 @@ import { get } from "svelte/store" import { BudiStore } from "../BudiStore" +import { componentStore } from "./components" +import { selectedScreen } from "./screens" type PreviewDevice = "desktop" | "tablet" | "mobile" type PreviewEventHandler = (name: string, payload?: any) => void @@ -54,10 +56,21 @@ export class PreviewStore extends BudiStore { })) } - startDrag(component: any) { + async startDrag(componentType: string) { + let componentId + const gridScreen = get(selectedScreen)?.props?.layout === "grid" + if (gridScreen) { + const component = await componentStore.create(componentType, { + _placeholder: true, + _styles: { normal: { opacity: 0 } }, + }) + componentId = component?._id + } this.sendEvent("dragging-new-component", { dragging: true, - component, + componentType, + componentId, + gridScreen, }) } diff --git a/packages/client/package.json b/packages/client/package.json index 2ae049f6d0..72be403698 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -5,7 +5,7 @@ "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", "type": "module", - "svelte": "src/index.js", + "svelte": "src/index.ts", "exports": { ".": { "import": "./dist/budibase-client.js", diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 2840d82f47..7144105fd8 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -44,6 +44,7 @@ import MaintenanceScreen from "components/MaintenanceScreen.svelte" import SnippetsProvider from "./context/SnippetsProvider.svelte" import EmbedProvider from "./context/EmbedProvider.svelte" + import GridNewComponentDNDHandler from "components/preview/GridNewComponentDNDHandler.svelte" // Provide contexts setContext("sdk", SDK) @@ -266,6 +267,7 @@ {#if $builderStore.inBuilder} + {/if} diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte new file mode 100644 index 0000000000..8a3da6f419 --- /dev/null +++ b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte @@ -0,0 +1,166 @@ + diff --git a/packages/client/src/index.d.ts b/packages/client/src/index.d.ts deleted file mode 100644 index 7e13670b33..0000000000 --- a/packages/client/src/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -interface Window { - "##BUDIBASE_APP_ID##": string - "##BUDIBASE_IN_BUILDER##": string - MIGRATING_APP: boolean -} diff --git a/packages/client/src/index.js b/packages/client/src/index.js deleted file mode 100644 index 8a48aa08e5..0000000000 --- a/packages/client/src/index.js +++ /dev/null @@ -1,138 +0,0 @@ -import ClientApp from "./components/ClientApp.svelte" -import UpdatingApp from "./components/UpdatingApp.svelte" -import { - builderStore, - appStore, - blockStore, - componentStore, - environmentStore, - dndStore, - eventStore, - hoverStore, - stateStore, -} from "./stores" -import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" -import { get } from "svelte/store" -import { initWebsocket } from "./websocket.js" - -// Provide svelte and svelte/internal as globals for custom components -import * as svelte from "svelte" -import * as internal from "svelte/internal" - -window.svelte_internal = internal -window.svelte = svelte - -// Initialise spectrum icons -loadSpectrumIcons() - -let app - -const loadBudibase = async () => { - // Update builder store with any builder flags - builderStore.set({ - ...get(builderStore), - inBuilder: !!window["##BUDIBASE_IN_BUILDER##"], - layout: window["##BUDIBASE_PREVIEW_LAYOUT##"], - screen: window["##BUDIBASE_PREVIEW_SCREEN##"], - selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"], - previewId: window["##BUDIBASE_PREVIEW_ID##"], - theme: window["##BUDIBASE_PREVIEW_THEME##"], - customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"], - previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"], - navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], - hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"], - usedPlugins: window["##BUDIBASE_USED_PLUGINS##"], - location: window["##BUDIBASE_LOCATION##"], - snippets: window["##BUDIBASE_SNIPPETS##"], - componentErrors: window["##BUDIBASE_COMPONENT_ERRORS##"], - }) - - // Set app ID - this window flag is set by both the preview and the real - // server rendered app HTML - appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"]) - - // Set the flag used to determine if the app is being loaded via an iframe - appStore.actions.setAppEmbedded( - window["##BUDIBASE_APP_EMBEDDED##"] === "true" - ) - - if (window.MIGRATING_APP) { - new UpdatingApp({ - target: window.document.body, - }) - return - } - - // Fetch environment info - if (!get(environmentStore)?.loaded) { - await environmentStore.actions.fetchEnvironment() - } - - // Register handler for runtime events from the builder - window.handleBuilderRuntimeEvent = (type, data) => { - if (!window["##BUDIBASE_IN_BUILDER##"]) { - return - } - if (type === "event-completed") { - eventStore.actions.resolveEvent(data) - } else if (type === "eject-block") { - const block = blockStore.actions.getBlock(data) - block?.eject() - } else if (type === "dragging-new-component") { - const { dragging, component } = data - if (dragging) { - const definition = - componentStore.actions.getComponentDefinition(component) - dndStore.actions.startDraggingNewComponent({ component, definition }) - } else { - dndStore.actions.reset() - } - } else if (type === "request-context") { - const { selectedComponentInstance, screenslotInstance } = - get(componentStore) - const instance = selectedComponentInstance || screenslotInstance - const context = instance?.getDataContext() - let stringifiedContext = null - try { - stringifiedContext = JSON.stringify(context) - } catch (error) { - // Ignore - invalid context - } - eventStore.actions.dispatchEvent("provide-context", { - context: stringifiedContext, - }) - } else if (type === "hover-component") { - hoverStore.actions.hoverComponent(data, false) - } else if (type === "builder-meta") { - builderStore.actions.setMetadata(data) - } else if (type === "builder-state") { - const [[key, value]] = Object.entries(data) - stateStore.actions.setValue(key, value) - } - } - - // Register any custom components - if (window["##BUDIBASE_CUSTOM_COMPONENTS##"]) { - window["##BUDIBASE_CUSTOM_COMPONENTS##"].forEach(component => { - componentStore.actions.registerCustomComponent(component) - }) - } - - // Make a callback available for custom component bundles to register - // themselves at runtime - window.registerCustomComponent = - componentStore.actions.registerCustomComponent - - // Initialise websocket - initWebsocket() - - // Create app if one hasn't been created yet - if (!app) { - app = new ClientApp({ - target: window.document.body, - }) - } -} - -// Attach to window so the HTML template can call this when it loads -window.loadBudibase = loadBudibase diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 08330a60fa..e7d454e2f1 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -1,6 +1,83 @@ +import ClientApp from "./components/ClientApp.svelte" +import UpdatingApp from "./components/UpdatingApp.svelte" +import { + builderStore, + appStore, + blockStore, + componentStore, + environmentStore, + dndStore, + eventStore, + hoverStore, + stateStore, +} from "@/stores" +import { get } from "svelte/store" +import { initWebsocket } from "@/websocket" import { APIClient } from "@budibase/frontend-core" -import type { ActionTypes } from "./constants" +import type { ActionTypes } from "@/constants" import { Readable } from "svelte/store" +import { + Screen, + Layout, + Theme, + AppCustomTheme, + PreviewDevice, + AppNavigation, + Plugin, + Snippet, + UIComponentError, + CustomComponent, +} from "@budibase/types" + +// Provide svelte and svelte/internal as globals for custom components +import * as svelte from "svelte" +// @ts-ignore +import * as internal from "svelte/internal" +window.svelte_internal = internal +window.svelte = svelte + +// Initialise spectrum icons +// eslint-disable-next-line local-rules/no-budibase-imports +import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" +loadSpectrumIcons() + +// Extend global window scope +declare global { + interface Window { + // Data from builder + "##BUDIBASE_APP_ID##"?: string + "##BUDIBASE_IN_BUILDER##"?: true + "##BUDIBASE_PREVIEW_LAYOUT##"?: Layout + "##BUDIBASE_PREVIEW_SCREEN##"?: Screen + "##BUDIBASE_SELECTED_COMPONENT_ID##"?: string + "##BUDIBASE_PREVIEW_ID##"?: number + "##BUDIBASE_PREVIEW_THEME##"?: Theme + "##BUDIBASE_PREVIEW_CUSTOM_THEME##"?: AppCustomTheme + "##BUDIBASE_PREVIEW_DEVICE##"?: PreviewDevice + "##BUDIBASE_APP_EMBEDDED##"?: string // This is a bool wrapped in a string + "##BUDIBASE_PREVIEW_NAVIGATION##"?: AppNavigation + "##BUDIBASE_HIDDEN_COMPONENT_IDS##"?: string[] + "##BUDIBASE_USED_PLUGINS##"?: Plugin[] + "##BUDIBASE_LOCATION##"?: { + protocol: string + hostname: string + port: string + } + "##BUDIBASE_SNIPPETS##"?: Snippet[] + "##BUDIBASE_COMPONENT_ERRORS##"?: Record[] + "##BUDIBASE_CUSTOM_COMPONENTS##"?: CustomComponent[] + + // Other flags + MIGRATING_APP: boolean + + // Client additions + handleBuilderRuntimeEvent: (type: string, data: any) => void + registerCustomComponent: typeof componentStore.actions.registerCustomComponent + loadBudibase: typeof loadBudibase + svelte: typeof svelte + svelte_internal: typeof internal + } +} export interface SDK { API: APIClient @@ -29,3 +106,119 @@ export type Component = Readable<{ }> export type Context = Readable<{}> + +let app: ClientApp + +const loadBudibase = async () => { + // Update builder store with any builder flags + builderStore.set({ + ...get(builderStore), + inBuilder: !!window["##BUDIBASE_IN_BUILDER##"], + layout: window["##BUDIBASE_PREVIEW_LAYOUT##"], + screen: window["##BUDIBASE_PREVIEW_SCREEN##"], + selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"], + previewId: window["##BUDIBASE_PREVIEW_ID##"], + theme: window["##BUDIBASE_PREVIEW_THEME##"], + customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"], + previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"], + navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], + hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"], + usedPlugins: window["##BUDIBASE_USED_PLUGINS##"], + location: window["##BUDIBASE_LOCATION##"], + snippets: window["##BUDIBASE_SNIPPETS##"], + componentErrors: window["##BUDIBASE_COMPONENT_ERRORS##"], + }) + + // Set app ID - this window flag is set by both the preview and the real + // server rendered app HTML + appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"]) + + // Set the flag used to determine if the app is being loaded via an iframe + appStore.actions.setAppEmbedded( + window["##BUDIBASE_APP_EMBEDDED##"] === "true" + ) + + if (window.MIGRATING_APP) { + new UpdatingApp({ + target: window.document.body, + }) + return + } + + // Fetch environment info + if (!get(environmentStore)?.loaded) { + await environmentStore.actions.fetchEnvironment() + } + + // Register handler for runtime events from the builder + window.handleBuilderRuntimeEvent = (type, data) => { + if (!window["##BUDIBASE_IN_BUILDER##"]) { + return + } + if (type === "event-completed") { + eventStore.actions.resolveEvent(data) + } else if (type === "eject-block") { + const block = blockStore.actions.getBlock(data) + block?.eject() + } else if (type === "dragging-new-component") { + const { dragging, component, componentId } = data + if (dragging) { + const definition = + componentStore.actions.getComponentDefinition(component) + dndStore.actions.startDraggingNewComponent({ + component, + definition, + componentId, + }) + } else { + dndStore.actions.reset() + } + } else if (type === "request-context") { + const { selectedComponentInstance, screenslotInstance } = + get(componentStore) + const instance = selectedComponentInstance || screenslotInstance + const context = instance?.getDataContext() + let stringifiedContext = null + try { + stringifiedContext = JSON.stringify(context) + } catch (error) { + // Ignore - invalid context + } + eventStore.actions.dispatchEvent("provide-context", { + context: stringifiedContext, + }) + } else if (type === "hover-component") { + hoverStore.actions.hoverComponent(data, false) + } else if (type === "builder-meta") { + builderStore.actions.setMetadata(data) + } else if (type === "builder-state") { + const [[key, value]] = Object.entries(data) + stateStore.actions.setValue(key, value) + } + } + + // Register any custom components + if (window["##BUDIBASE_CUSTOM_COMPONENTS##"]) { + window["##BUDIBASE_CUSTOM_COMPONENTS##"].forEach(component => { + componentStore.actions.registerCustomComponent(component) + }) + } + + // Make a callback available for custom component bundles to register + // themselves at runtime + window.registerCustomComponent = + componentStore.actions.registerCustomComponent + + // Initialise websocket + initWebsocket() + + // Create app if one hasn't been created yet + if (!app) { + app = new ClientApp({ + target: window.document.body, + }) + } +} + +// Attach to window so the HTML template can call this when it loads +window.loadBudibase = loadBudibase diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 43d4eeeed8..5cfb12c7d2 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -21,7 +21,11 @@ const createDndStore = () => { }) } - const startDraggingNewComponent = ({ component, definition }) => { + const startDraggingNewComponent = ({ + component, + definition, + componentId, + }) => { if (!component) { return } @@ -38,6 +42,7 @@ const createDndStore = () => { bounds: { height, width }, index: null, newComponentType: component, + newComponentId: componentId, }, }) } @@ -82,6 +87,10 @@ export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) +export const dndNewComponentId = derivedMemo( + dndStore, + x => x.source?.newComponentId +) export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index f2b80ed732..268b0cc4bf 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -2,7 +2,7 @@ export { authStore } from "./auth" export { appStore } from "./app" export { notificationStore } from "./notification" export { routeStore } from "./routes" -export { screenStore } from "./screens" +export { screenStore, isGridScreen } from "./screens" export { builderStore } from "./builder" export { dataSourceStore } from "./dataSource" export { confirmationStore } from "./confirmation" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index a7277ca2b5..f85675e389 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -198,3 +198,7 @@ const createScreenStore = () => { } export const screenStore = createScreenStore() + +export const isGridScreen = derived(screenStore, $screenStore => { + return $screenStore.activeScreen?.props?.layout === "grid" +}) diff --git a/packages/client/vite.config.mjs b/packages/client/vite.config.mjs index 7c163181ae..9ef87d8ec8 100644 --- a/packages/client/vite.config.mjs +++ b/packages/client/vite.config.mjs @@ -20,7 +20,7 @@ export default defineConfig(({ mode }) => { }, build: { lib: { - entry: "src/index.js", + entry: "src/index.ts", formats: ["iife"], outDir: "dist", name: "budibase_client", @@ -67,10 +67,6 @@ export default defineConfig(({ mode }) => { find: "constants", replacement: path.resolve("./src/constants"), }, - { - find: "@/constants", - replacement: path.resolve("./src/constants"), - }, { find: "sdk", replacement: path.resolve("./src/sdk"), @@ -87,6 +83,10 @@ export default defineConfig(({ mode }) => { find: "@budibase/bbui", replacement: path.resolve("../bbui/src"), }, + { + find: "@", + replacement: path.resolve(__dirname, "src"), + }, ], }, } diff --git a/packages/types/src/ui/components/index.ts b/packages/types/src/ui/components/index.ts index 283ceb47da..85c7b1af84 100644 --- a/packages/types/src/ui/components/index.ts +++ b/packages/types/src/ui/components/index.ts @@ -2,6 +2,16 @@ export * from "./sidepanel" export * from "./codeEditor" export * from "./errors" +export interface CustomComponent { + Component: any + schema: { + type: "component" + metadata: Record + schema: ComponentDefinition + } + version: string +} + export interface ComponentDefinition { component: string name: string From 5b5a0d2ba80218758985d695655a6513408fd6dd Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 14:55:05 +0000 Subject: [PATCH 02/64] Add working DND placeholder support for grid screens --- .../new/_components/NewComponentPanel.svelte | 3 +- .../[screenId]/_components/AppPreview.svelte | 4 +- .../builder/src/stores/builder/preview.ts | 17 +--- .../src/components/preview/DNDHandler.svelte | 23 ++++-- .../preview/DNDPlaceholderOverlay.svelte | 33 ++++++-- .../components/preview/GridDNDHandler.svelte | 78 +++++++++++++++++-- packages/client/src/index.ts | 5 +- packages/client/src/stores/builder.js | 3 +- packages/client/src/stores/dnd.js | 68 +++++++++++++--- packages/client/src/stores/index.js | 1 + packages/client/src/stores/screens.js | 3 +- 11 files changed, 185 insertions(+), 53 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index 784642787b..c76b03be36 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -223,11 +223,13 @@ }) const onDragStart = (e, component) => { + console.log("DRAG START") e.dataTransfer.setDragImage(ghost, 0, 0) previewStore.startDrag(component) } const onDragEnd = () => { + console.log("DRAG END") previewStore.stopDrag() } @@ -314,7 +316,6 @@ } .component:hover { background: var(--spectrum-global-color-gray-300); - cursor: grab; } .component :global(.spectrum-Body) { line-height: 1.2 !important; diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte index 3951c0e902..39e0835fa8 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte @@ -199,8 +199,8 @@ } else if (type === "reload-plugin") { await componentStore.refreshDefinitions() } else if (type === "drop-new-component") { - const { component, parent, index } = data - await componentStore.create(component, null, parent, index) + const { component, parent, index, props } = data + await componentStore.create(component, props, parent, index) } else if (type === "add-parent-component") { const { componentId, parentType } = data await componentStore.addParent(componentId, parentType) diff --git a/packages/builder/src/stores/builder/preview.ts b/packages/builder/src/stores/builder/preview.ts index 9aeaf99346..a382eeefb0 100644 --- a/packages/builder/src/stores/builder/preview.ts +++ b/packages/builder/src/stores/builder/preview.ts @@ -1,7 +1,5 @@ import { get } from "svelte/store" import { BudiStore } from "../BudiStore" -import { componentStore } from "./components" -import { selectedScreen } from "./screens" type PreviewDevice = "desktop" | "tablet" | "mobile" type PreviewEventHandler = (name: string, payload?: any) => void @@ -56,21 +54,10 @@ export class PreviewStore extends BudiStore { })) } - async startDrag(componentType: string) { - let componentId - const gridScreen = get(selectedScreen)?.props?.layout === "grid" - if (gridScreen) { - const component = await componentStore.create(componentType, { - _placeholder: true, - _styles: { normal: { opacity: 0 } }, - }) - componentId = component?._id - } + async startDrag(component: string) { this.sendEvent("dragging-new-component", { dragging: true, - componentType, - componentId, - gridScreen, + component, }) } diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index bdd538748b..11bed5a1b7 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -8,12 +8,14 @@ dndStore, dndParent, dndIsDragging, + isGridScreen, + dndInitialised, } from "stores" import DNDPlaceholderOverlay from "./DNDPlaceholderOverlay.svelte" import { Utils } from "@budibase/frontend-core" - import { findComponentById } from "utils/components.js" - import { DNDPlaceholderID } from "constants" - import { isGridEvent } from "utils/grid" + import { findComponentById } from "@/utils/components.js" + import { isGridEvent } from "@/utils/grid" + import { DNDPlaceholderID } from "@/constants" const ThrottleRate = 130 @@ -219,9 +221,9 @@ processEvent(e.clientX, e.clientY) } - // Callback when on top of a component. + // Callback when on top of a component const onDragOver = e => { - if (!source || !target) { + if (!source || !target || $isGridScreen) { return } handleEvent(e) @@ -233,6 +235,14 @@ return } + // Mark as initialised if this is our first valid drag enter event + if (!$dndInitialised) { + dndStore.actions.markInitialised() + } + if ($isGridScreen) { + return + } + // Find the next valid component to consider dropping over, ignoring nested // block components const component = e.target?.closest?.( @@ -262,7 +272,8 @@ builderStore.actions.dropNewComponent( source.newComponentType, drop.parent, - drop.index + drop.index, + $dndStore.meta.newComponentProps ) dropping = false stopDragging() diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 61cecc885b..50b76c6208 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,38 +1,56 @@ -{#if left != null && top != null && width && height} +{#if left != null && top != null && width && height && $dndInitialised}
diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index f173dfd960..3d50bfded9 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -1,15 +1,22 @@ diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index e7d454e2f1..7d6b100dc6 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -36,6 +36,8 @@ import * as internal from "svelte/internal" window.svelte_internal = internal window.svelte = svelte +console.log("NEW CLIENT") + // Initialise spectrum icons // eslint-disable-next-line local-rules/no-budibase-imports import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" @@ -161,14 +163,13 @@ const loadBudibase = async () => { const block = blockStore.actions.getBlock(data) block?.eject() } else if (type === "dragging-new-component") { - const { dragging, component, componentId } = data + const { dragging, component } = data if (dragging) { const definition = componentStore.actions.getComponentDefinition(component) dndStore.actions.startDraggingNewComponent({ component, definition, - componentId, }) } else { dndStore.actions.reset() diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 1ae7d3a670..7effd718a0 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -77,11 +77,12 @@ const createBuilderStore = () => { mode, }) }, - dropNewComponent: (component, parent, index) => { + dropNewComponent: (component, parent, index, props) => { eventStore.actions.dispatchEvent("drop-new-component", { component, parent, index, + props, }) }, setEditMode: enabled => { diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 5cfb12c7d2..74987ea7d9 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -1,5 +1,7 @@ -import { writable } from "svelte/store" +import { writable, get } from "svelte/store" import { derivedMemo } from "@budibase/frontend-core" +import { screenStore } from "@/stores" +import { ScreenslotID } from "@/constants" const createDndStore = () => { const initialState = { @@ -11,6 +13,12 @@ const createDndStore = () => { // Info about where the component would be dropped drop: null, + + // Metadata about the event + meta: { + initialised: false, + newComponentProps: null, + }, } const store = writable(initialState) @@ -21,35 +29,53 @@ const createDndStore = () => { }) } - const startDraggingNewComponent = ({ - component, - definition, - componentId, - }) => { + const startDraggingNewComponent = ({ component, definition }) => { + console.log("start", component, definition) if (!component) { return } + let target, drop + const screen = get(screenStore)?.activeScreen + const isGridScreen = screen?.props?.layout === "grid" + if (isGridScreen) { + const id = screen?.props?._id + drop = { + parent: id, + index: screen?.props?._children?.length, + } + target = { + id, + parent: ScreenslotID, + node: null, + empty: false, + acceptsChildren: true, + } + } + // Get size of new component so we can show a properly sized placeholder const width = definition?.size?.width || 128 const height = definition?.size?.height || 64 store.set({ ...initialState, + isGridScreen, source: { id: null, parent: null, bounds: { height, width }, index: null, newComponentType: component, - newComponentId: componentId, }, + target, + drop, }) } const updateTarget = ({ id, parent, node, empty, acceptsChildren }) => { store.update(state => { state.target = { id, parent, node, empty, acceptsChildren } + console.log("TARGET", state.target) return state }) } @@ -57,6 +83,7 @@ const createDndStore = () => { const updateDrop = ({ parent, index }) => { store.update(state => { state.drop = { parent, index } + console.log("DROP", state.drop) return state }) } @@ -65,6 +92,26 @@ const createDndStore = () => { store.set(initialState) } + const markInitialised = () => { + store.update(state => ({ + ...state, + meta: { + ...state.meta, + initialised: true, + }, + })) + } + + const updateNewComponentProps = newComponentProps => { + store.update(state => ({ + ...state, + meta: { + ...state.meta, + newComponentProps, + }, + })) + } + return { subscribe: store.subscribe, actions: { @@ -73,6 +120,8 @@ const createDndStore = () => { updateTarget, updateDrop, reset, + markInitialised, + updateNewComponentProps, }, } } @@ -87,10 +136,7 @@ export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) -export const dndNewComponentId = derivedMemo( - dndStore, - x => x.source?.newComponentId -) +export const dndInitialised = derivedMemo(dndStore, x => x.meta.initialised) export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 268b0cc4bf..b1f0f8955a 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -25,6 +25,7 @@ export { dndBounds, dndIsNewComponent, dndIsDragging, + dndInitialised, } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index f85675e389..6193dcca94 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -7,7 +7,7 @@ import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js" import { RoleUtils } from "@budibase/frontend-core" import { findComponentById, findComponentParent } from "../utils/components.js" import { Helpers } from "@budibase/bbui" -import { DNDPlaceholderID, ScreenslotID, ScreenslotType } from "constants" +import { DNDPlaceholderID, ScreenslotID, ScreenslotType } from "@/constants" const createScreenStore = () => { const store = derived( @@ -99,7 +99,6 @@ const createScreenStore = () => { normal: { width: `${$dndBounds?.width || 400}px`, height: `${$dndBounds?.height || 200}px`, - opacity: 0, "--default-width": $dndBounds?.width || 400, "--default-height": $dndBounds?.height || 200, }, From b9c2b07f3e7d696a7956e0b1c9e492bd00be8cfe Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 16:16:22 +0000 Subject: [PATCH 03/64] Finally actually fix devilish issue of flashing placeholder overlay --- .../src/components/preview/DNDHandler.svelte | 27 ++++++-------- .../preview/DNDPlaceholderOverlay.svelte | 36 ++++++++++++++++--- .../components/preview/GridDNDHandler.svelte | 21 ++++++----- .../preview/SelectionIndicator.svelte | 4 +-- packages/client/src/stores/dnd.js | 18 +++------- packages/client/src/stores/index.js | 2 +- packages/client/src/stores/screens.js | 1 + 7 files changed, 62 insertions(+), 47 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 11bed5a1b7..f62f21e94c 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -9,7 +9,6 @@ dndParent, dndIsDragging, isGridScreen, - dndInitialised, } from "stores" import DNDPlaceholderOverlay from "./DNDPlaceholderOverlay.svelte" import { Utils } from "@budibase/frontend-core" @@ -230,16 +229,8 @@ } // Callback when entering a potential drop target - const onDragEnter = e => { - if (!source) { - return - } - - // Mark as initialised if this is our first valid drag enter event - if (!$dndInitialised) { - dndStore.actions.markInitialised() - } - if ($isGridScreen) { + const onDragEnter = async e => { + if (!source || $isGridScreen) { return } @@ -345,12 +336,14 @@ }) - +{#if !$isGridScreen} + +{/if} {#if $dndIsDragging} diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 50b76c6208..5593fa010d 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,14 +1,38 @@ -{#if left != null && top != null && width && height && $dndInitialised} +{#if left != null && top != null && width && height && !waitingForGrid}
{/if} @@ -65,4 +90,7 @@ border-radius: 4px; border: 2px solid var(--spectrum-global-color-static-green-500); } + .overlay.animate { + transition: all 130ms ease-out; + } diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 3d50bfded9..4f810d226f 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -42,23 +42,26 @@ // Set ephemeral styles $: instance = componentStore.actions.getComponentInstance(id) - $: $instance?.setEphemeralStyles($styles) + $: applyStyles($instance, $styles) - // Keep DND store up to date with grid styles if dragging a new component - // on to a grid screen - $: { - if ($dndIsNewComponent) { + // Reset when not dragging new components + $: !$dndIsDragging && stopDragging() + + const applyStyles = async (instance, styles) => { + instance?.setEphemeralStyles(styles) + + // If dragging a new component on to a grid screen, tick to allow the + // real component to render in the new position before updating the DND + // store, preventing the green DND overlay from being out of position + if ($dndIsNewComponent && styles) { dndStore.actions.updateNewComponentProps({ _styles: { - normal: $styles, + normal: styles, }, }) } } - // Reset when not dragging new components - $: !$dndIsDragging && stopDragging() - // Sugar for a combination of both min and max const minMax = (value, min, max) => Math.min(max, Math.max(min, value)) diff --git a/packages/client/src/components/preview/SelectionIndicator.svelte b/packages/client/src/components/preview/SelectionIndicator.svelte index a271389cbd..5c34fe6f42 100644 --- a/packages/client/src/components/preview/SelectionIndicator.svelte +++ b/packages/client/src/components/preview/SelectionIndicator.svelte @@ -1,5 +1,5 @@ { // Metadata about the event meta: { - initialised: false, newComponentProps: null, }, } @@ -30,7 +29,6 @@ const createDndStore = () => { } const startDraggingNewComponent = ({ component, definition }) => { - console.log("start", component, definition) if (!component) { return } @@ -92,16 +90,6 @@ const createDndStore = () => { store.set(initialState) } - const markInitialised = () => { - store.update(state => ({ - ...state, - meta: { - ...state.meta, - initialised: true, - }, - })) - } - const updateNewComponentProps = newComponentProps => { store.update(state => ({ ...state, @@ -120,7 +108,6 @@ const createDndStore = () => { updateTarget, updateDrop, reset, - markInitialised, updateNewComponentProps, }, } @@ -136,8 +123,11 @@ export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) -export const dndInitialised = derivedMemo(dndStore, x => x.meta.initialised) export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null ) +export const dndNewComponentProps = derivedMemo( + dndStore, + x => x.meta?.newComponentProps +) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index b1f0f8955a..7d8257f6d0 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -25,7 +25,7 @@ export { dndBounds, dndIsNewComponent, dndIsDragging, - dndInitialised, + dndNewComponentProps, } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index 6193dcca94..99b943fbd2 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -99,6 +99,7 @@ const createScreenStore = () => { normal: { width: `${$dndBounds?.width || 400}px`, height: `${$dndBounds?.height || 200}px`, + opacity: 0, "--default-width": $dndBounds?.width || 400, "--default-height": $dndBounds?.height || 200, }, From e71e8ff6b68fcc61762ebdcaa053bd447ba53de0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 16:20:31 +0000 Subject: [PATCH 04/64] Tidy up --- .../components/preview/GridDNDHandler.svelte | 2 -- packages/client/src/index.ts | 2 -- packages/client/src/stores/dnd.js | 21 +++++++------------ packages/client/src/stores/index.js | 1 - 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 4f810d226f..6ada5b4b4b 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -124,7 +124,6 @@ } const startDraggingPlaceholder = () => { - console.log("START PLACEHOLDER") const mode = GridDragModes.Move const id = DNDPlaceholderID @@ -160,7 +159,6 @@ } // Add event handler to clear all drag state when dragging ends - console.log("add up listener") document.addEventListener("mouseup", stopDragging) } diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 7d6b100dc6..20f582106b 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -36,8 +36,6 @@ import * as internal from "svelte/internal" window.svelte_internal = internal window.svelte = svelte -console.log("NEW CLIENT") - // Initialise spectrum icons // eslint-disable-next-line local-rules/no-budibase-imports import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 16f1441950..38c1e8aab8 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -1,6 +1,6 @@ import { writable, get } from "svelte/store" import { derivedMemo } from "@budibase/frontend-core" -import { screenStore } from "@/stores" +import { screenStore, isGridScreen } from "@/stores" import { ScreenslotID } from "@/constants" const createDndStore = () => { @@ -33,15 +33,11 @@ const createDndStore = () => { return } + // On grid screens, we already know exactly where to insert the component let target, drop const screen = get(screenStore)?.activeScreen - const isGridScreen = screen?.props?.layout === "grid" - if (isGridScreen) { + if (get(isGridScreen)) { const id = screen?.props?._id - drop = { - parent: id, - index: screen?.props?._children?.length, - } target = { id, parent: ScreenslotID, @@ -49,6 +45,10 @@ const createDndStore = () => { empty: false, acceptsChildren: true, } + drop = { + parent: id, + index: screen?.props?._children?.length, + } } // Get size of new component so we can show a properly sized placeholder @@ -57,7 +57,6 @@ const createDndStore = () => { store.set({ ...initialState, - isGridScreen, source: { id: null, parent: null, @@ -73,7 +72,6 @@ const createDndStore = () => { const updateTarget = ({ id, parent, node, empty, acceptsChildren }) => { store.update(state => { state.target = { id, parent, node, empty, acceptsChildren } - console.log("TARGET", state.target) return state }) } @@ -81,7 +79,6 @@ const createDndStore = () => { const updateDrop = ({ parent, index }) => { store.update(state => { state.drop = { parent, index } - console.log("DROP", state.drop) return state }) } @@ -127,7 +124,3 @@ export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null ) -export const dndNewComponentProps = derivedMemo( - dndStore, - x => x.meta?.newComponentProps -) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 7d8257f6d0..268b0cc4bf 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -25,7 +25,6 @@ export { dndBounds, dndIsNewComponent, dndIsDragging, - dndNewComponentProps, } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" From 0471e113e37103831910f3faeaf66363de132148 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 16:31:38 +0000 Subject: [PATCH 05/64] More tidy up --- .../new/_components/NewComponentPanel.svelte | 2 -- .../components/preview/GridDNDHandler.svelte | 17 +++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index c76b03be36..f80b681782 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -223,13 +223,11 @@ }) const onDragStart = (e, component) => { - console.log("DRAG START") e.dataTransfer.setDragImage(ghost, 0, 0) previewStore.startDrag(component) } const onDragEnd = () => { - console.log("DRAG END") previewStore.stopDrag() } diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 6ada5b4b4b..569a9879a6 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -123,12 +123,10 @@ processEvent(e.clientX, e.clientY) } + // Callback when dragging a new component over the preview iframe in a valid + // position for the first time const startDraggingPlaceholder = () => { - const mode = GridDragModes.Move - const id = DNDPlaceholderID - - // Find grid parent and read from DOM - const domComponent = document.getElementsByClassName(id)[0] + const domComponent = document.getElementsByClassName(DNDPlaceholderID)[0] const domGrid = domComponent?.closest(".grid") if (!domGrid) { return @@ -139,15 +137,14 @@ // Show as active domComponent.classList.add("dragging") domGrid.classList.add("highlight") - builderStore.actions.selectComponent(id) // Update state dragInfo = { domComponent, domGrid, - id, + id: DNDPlaceholderID, gridId: domGrid.parentNode.dataset.id, - mode, + mode: GridDragModes.Move, grid: { startX: bounds.left + bounds.width / 2, startY: bounds.top + bounds.height / 2, @@ -157,9 +154,6 @@ colEnd: parseInt(styles["grid-column-end"]), }, } - - // Add event handler to clear all drag state when dragging ends - document.addEventListener("mouseup", stopDragging) } // Callback when initially starting a drag on a draggable component @@ -266,6 +260,5 @@ onDestroy(() => { document.removeEventListener("dragstart", onDragStart, false) document.removeEventListener("dragover", onDragOver, false) - document.removeEventListener("mouseup", stopDragging, false) }) From 0ad0ded2e2febf94370fdda88643833cda4d60ba Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 09:13:20 +0000 Subject: [PATCH 06/64] Use new technique for DND selection indicators --- .../client/src/components/ClientApp.svelte | 4 +- .../client/src/components/Component.svelte | 2 +- .../src/components/preview/DNDHandler.svelte | 21 +- .../preview/DNDPlaceholderOverlay.svelte | 186 ++++++++++-------- .../preview/DNDSelectionIndicators.svelte | 27 +++ .../components/preview/GridDNDHandler.svelte | 6 +- .../src/components/preview/Indicator.svelte | 10 +- .../components/preview/IndicatorSet.svelte | 31 +-- packages/client/src/stores/dnd.js | 22 ++- packages/client/src/stores/index.js | 9 +- packages/client/src/stores/screens.js | 18 +- 11 files changed, 188 insertions(+), 148 deletions(-) create mode 100644 packages/client/src/components/preview/DNDSelectionIndicators.svelte diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 7144105fd8..144b5a8dec 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -44,7 +44,7 @@ import MaintenanceScreen from "components/MaintenanceScreen.svelte" import SnippetsProvider from "./context/SnippetsProvider.svelte" import EmbedProvider from "./context/EmbedProvider.svelte" - import GridNewComponentDNDHandler from "components/preview/GridNewComponentDNDHandler.svelte" + import DNDSelectionIndicators from "./preview/DNDSelectionIndicators.svelte" // Provide contexts setContext("sdk", SDK) @@ -267,7 +267,7 @@ {#if $builderStore.inBuilder} - + {/if}
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 3e22ffada1..67f8fdc63c 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -120,7 +120,7 @@ $: children = instance._children || [] $: id = instance._id $: name = isRoot ? "Screen" : instance._instanceName - $: icon = definition?.icon + $: icon = instance._icon || definition?.icon // Determine if the component is selected or is part of the critical path // leading to the selected component diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index f62f21e94c..82db06a623 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -7,10 +7,10 @@ screenStore, dndStore, dndParent, + dndSource, dndIsDragging, isGridScreen, } from "stores" - import DNDPlaceholderOverlay from "./DNDPlaceholderOverlay.svelte" import { Utils } from "@budibase/frontend-core" import { findComponentById } from "@/utils/components.js" import { isGridEvent } from "@/utils/grid" @@ -92,6 +92,8 @@ bounds: component.children[0].getBoundingClientRect(), parent: parentId, index, + name: component.dataset.name, + icon: component.dataset.icon, }) builderStore.actions.selectComponent(id) @@ -258,10 +260,10 @@ } // Check if we're adding a new component rather than moving one - if (source.newComponentType) { + if (source.isNew) { dropping = true builderStore.actions.dropNewComponent( - source.newComponentType, + source.type, drop.parent, drop.index, $dndStore.meta.newComponentProps @@ -335,16 +337,3 @@ document.removeEventListener("drop", onDrop, false) }) - -{#if !$isGridScreen} - -{/if} - -{#if $dndIsDragging} - -{/if} diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 5593fa010d..f06454acce 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,96 +1,108 @@ - + + + + + + + -{#if left != null && top != null && width && height && !waitingForGrid} -
-{/if} + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte new file mode 100644 index 0000000000..9949f07ace --- /dev/null +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -0,0 +1,27 @@ + + +{#if !$isGridScreen} + +{/if} + +{#if $dndIsDragging} + +{/if} diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 569a9879a6..58ba92ab07 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -4,8 +4,8 @@ builderStore, componentStore, dndIsDragging, - dndIsNewComponent, dndStore, + dndSource, isGridScreen, } from "stores" import { Utils, memo } from "@budibase/frontend-core" @@ -53,7 +53,7 @@ // If dragging a new component on to a grid screen, tick to allow the // real component to render in the new position before updating the DND // store, preventing the green DND overlay from being out of position - if ($dndIsNewComponent && styles) { + if ($dndSource?.isNew && styles) { dndStore.actions.updateNewComponentProps({ _styles: { normal: styles, @@ -222,7 +222,7 @@ const onDragOver = e => { if (!dragInfo) { // Check if we're dragging a new component - if ($dndIsDragging && $dndIsNewComponent && $isGridScreen) { + if ($dndIsDragging && $dndSource?.isNew && $isGridScreen) { startDraggingPlaceholder() } return diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index dce7945b29..94940285ff 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -14,6 +14,8 @@ export let line = false export let alignRight = false export let showResizeAnchors = false + export let background = null + export let animate = false const AnchorSides = [ "right", @@ -33,10 +35,12 @@ class="indicator" class:flipped class:line - style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color}; --zIndex: {zIndex};" + style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color}; --zIndex: {zIndex}; --bg: {background || + 'none'};" class:withText={!!text} class:vCompact={height < 40} class:hCompact={width < 40} + class:animate > {#if text || icon}
{ mutationObserver.observe(element, { attributes: true, - attributeFilter: ["style"], }) observingMutations = true } @@ -108,17 +111,19 @@ } // Check if we're inside a grid - if (allowResizeAnchors) { - nextState.insideGrid = elements[0]?.dataset.insideGrid === "true" - } + nextState.insideGrid = elements[0]?.dataset.insideGrid === "true" - // Get text to display - nextState.text = elements[0].dataset.name - if (nextState.prefix) { - nextState.text = `${nextState.prefix} ${nextState.text}` + // Get text and icon to display + if (!text) { + nextState.text = elements[0].dataset.name + if (nextState.prefix) { + nextState.text = `${nextState.prefix} ${nextState.text}` + } } - if (elements[0].dataset.icon) { - nextState.icon = elements[0].dataset.icon + if (!icon) { + if (elements[0].dataset.icon) { + nextState.icon = elements[0].dataset.icon + } } nextState.error = elements[0].classList.contains("error") @@ -205,5 +210,7 @@ color={state.error ? errorColor : state.color} componentId={state.componentId} zIndex={state.zIndex} + {background} + {animate} /> {/each} diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 38c1e8aab8..f6b8fec48c 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -21,10 +21,17 @@ const createDndStore = () => { } const store = writable(initialState) - const startDraggingExistingComponent = ({ id, parent, bounds, index }) => { + const startDraggingExistingComponent = ({ + id, + parent, + bounds, + index, + name, + icon, + }) => { store.set({ ...initialState, - source: { id, parent, bounds, index }, + source: { id, parent, bounds, index, name, icon, isNew: false }, }) } @@ -62,7 +69,10 @@ const createDndStore = () => { parent: null, bounds: { height, width }, index: null, - newComponentType: component, + type: component, + isNew: true, + name: `New ${definition.name}`, + icon: definition.icon, }, target, drop, @@ -118,9 +128,5 @@ export const dndStore = createDndStore() // or components which depend on DND state unless values actually change. export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) -export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) +export const dndSource = derivedMemo(dndStore, x => x.source) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) -export const dndIsNewComponent = derivedMemo( - dndStore, - x => x.source?.newComponentType != null -) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 268b0cc4bf..522fadc643 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -18,14 +18,7 @@ export { environmentStore } from "./environment" export { eventStore } from "./events" export { orgStore } from "./org" export { roleStore } from "./roles" -export { - dndStore, - dndIndex, - dndParent, - dndBounds, - dndIsNewComponent, - dndIsDragging, -} from "./dnd" +export { dndStore, dndIndex, dndParent, dndIsDragging, dndSource } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" export { hoverStore } from "./hover" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index 99b943fbd2..df0dc0e365 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -3,7 +3,7 @@ import { routeStore } from "./routes" import { builderStore } from "./builder" import { appStore } from "./app" import { orgStore } from "./org" -import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js" +import { dndIndex, dndParent, dndSource } from "./dnd.js" import { RoleUtils } from "@budibase/frontend-core" import { findComponentById, findComponentParent } from "../utils/components.js" import { Helpers } from "@budibase/bbui" @@ -18,8 +18,7 @@ const createScreenStore = () => { orgStore, dndParent, dndIndex, - dndIsNewComponent, - dndBounds, + dndSource, ], ([ $appStore, @@ -28,8 +27,7 @@ const createScreenStore = () => { $orgStore, $dndParent, $dndIndex, - $dndIsNewComponent, - $dndBounds, + $dndSource, ]) => { let activeLayout, activeScreen let screens @@ -85,7 +83,7 @@ const createScreenStore = () => { // Remove selected component from tree if we are moving an existing // component - if (!$dndIsNewComponent && selectedParent) { + if (!$dndSource.isNew && selectedParent) { selectedParent._children = selectedParent._children?.filter( x => x._id !== selectedComponentId ) @@ -97,11 +95,11 @@ const createScreenStore = () => { _id: DNDPlaceholderID, _styles: { normal: { - width: `${$dndBounds?.width || 400}px`, - height: `${$dndBounds?.height || 200}px`, + width: `${$dndSource?.bounds?.width || 400}px`, + height: `${$dndSource?.bounds?.height || 200}px`, opacity: 0, - "--default-width": $dndBounds?.width || 400, - "--default-height": $dndBounds?.height || 200, + "--default-width": $dndSource?.bounds?.width || 400, + "--default-height": $dndSource?.bounds?.height || 200, }, }, static: true, From 89d6231dad6a0f13999471237704e7cd9a09d2c2 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 09:47:09 +0000 Subject: [PATCH 07/64] Type IndicatorSet --- .../preview/DNDSelectionIndicators.svelte | 20 ++-- .../components/preview/IndicatorSet.svelte | 107 +++++++++++------- 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte index 9949f07ace..cb81e83a6b 100644 --- a/packages/client/src/components/preview/DNDSelectionIndicators.svelte +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -1,19 +1,19 @@ -{#if !$isGridScreen} - -{/if} - {#if $dndIsDragging} + {#if !$isGridScreen} + + {/if} + + - +{#if !$dndIsDragging && componentId} + +{/if}} diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index 94940285ff..b14807e535 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -1,20 +1,20 @@ - - +{#if !$dndIsDragging && $builderStore.selectedComponentId} + +{/if} From a541603267ceb664f1fb3a36343af98f01a326ef Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 09:57:04 +0000 Subject: [PATCH 09/64] Type hover and selection indicators --- .../src/components/preview/HoverIndicator.svelte | 16 ++++++++++------ .../components/preview/SelectionIndicator.svelte | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index 4930fc35eb..d8846bdb42 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -1,4 +1,4 @@ - diff --git a/packages/client/src/components/context/RowSelectionProvider.svelte b/packages/client/src/components/context/RowSelectionProvider.svelte index 2c87a5fa00..da731e6f05 100644 --- a/packages/client/src/components/context/RowSelectionProvider.svelte +++ b/packages/client/src/components/context/RowSelectionProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/context/SnippetsProvider.svelte b/packages/client/src/components/context/SnippetsProvider.svelte index 53fa1e8b7f..104147ecf7 100644 --- a/packages/client/src/components/context/SnippetsProvider.svelte +++ b/packages/client/src/components/context/SnippetsProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/context/StateBindingsProvider.svelte b/packages/client/src/components/context/StateBindingsProvider.svelte index a1166594a8..4ef99228c1 100644 --- a/packages/client/src/components/context/StateBindingsProvider.svelte +++ b/packages/client/src/components/context/StateBindingsProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/context/UserBindingsProvider.svelte b/packages/client/src/components/context/UserBindingsProvider.svelte index 98769cf76a..4cfb804998 100644 --- a/packages/client/src/components/context/UserBindingsProvider.svelte +++ b/packages/client/src/components/context/UserBindingsProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte b/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte index 3b4c426851..6e020c06f4 100644 --- a/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte +++ b/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/overlay/ConfirmationDisplay.svelte b/packages/client/src/components/overlay/ConfirmationDisplay.svelte index b96af502df..823c1c1ab2 100644 --- a/packages/client/src/components/overlay/ConfirmationDisplay.svelte +++ b/packages/client/src/components/overlay/ConfirmationDisplay.svelte @@ -1,5 +1,5 @@ diff --git a/packages/client/src/components/overlay/NotificationDisplay.svelte b/packages/client/src/components/overlay/NotificationDisplay.svelte index 46b3a2a6a1..28f4b33433 100644 --- a/packages/client/src/components/overlay/NotificationDisplay.svelte +++ b/packages/client/src/components/overlay/NotificationDisplay.svelte @@ -1,5 +1,5 @@ diff --git a/packages/client/src/components/overlay/PeekScreenDisplay.svelte b/packages/client/src/components/overlay/PeekScreenDisplay.svelte index 6e0fa81b43..17a92797d5 100644 --- a/packages/client/src/components/overlay/PeekScreenDisplay.svelte +++ b/packages/client/src/components/overlay/PeekScreenDisplay.svelte @@ -5,7 +5,7 @@ notificationStore, routeStore, stateStore, - } from "stores" + } from "@/stores" import { Modal, ModalContent, ActionButton } from "@budibase/bbui" import { onDestroy } from "svelte" diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 82db06a623..263be016fc 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -10,7 +10,7 @@ dndSource, dndIsDragging, isGridScreen, - } from "stores" + } from "@/stores" import { Utils } from "@budibase/frontend-core" import { findComponentById } from "@/utils/components.js" import { isGridEvent } from "@/utils/grid" @@ -266,7 +266,7 @@ source.type, drop.parent, drop.index, - $dndStore.meta.newComponentProps + $dndStore.source?.props ) dropping = false stopDragging() diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte index cb81e83a6b..42f2e464cc 100644 --- a/packages/client/src/components/preview/DNDSelectionIndicators.svelte +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -1,5 +1,5 @@ diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 58ba92ab07..e2414e9d78 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -7,7 +7,7 @@ dndStore, dndSource, isGridScreen, - } from "stores" + } from "@/stores" import { Utils, memo } from "@budibase/frontend-core" import { DNDPlaceholderID, GridRowHeight } from "@/constants" import { @@ -54,7 +54,7 @@ // real component to render in the new position before updating the DND // store, preventing the green DND overlay from being out of position if ($dndSource?.isNew && styles) { - dndStore.actions.updateNewComponentProps({ + dndStore.actions.updateSourceProps({ _styles: { normal: styles, }, diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte index 8a3da6f419..4a444b59e9 100644 --- a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte +++ b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte index 4a444b59e9..a705561294 100644 --- a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte +++ b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte @@ -2,8 +2,8 @@ import { onDestroy, getContext } from "svelte" import { builderStore, componentStore, screenStore } from "@/stores" import { Utils, memo } from "@budibase/frontend-core" - import { GridRowHeight } from "constants" - import { GridParams, getGridVar, Devices } from "utils/grid" + import { GridRowHeight } from "@/constants" + import { GridParams, getGridVar, Devices } from "@/utils/grid" const context = getContext("context") diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index d8846bdb42..981e82bc2e 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -1,7 +1,7 @@ {#if $dndIsDragging} - {#if !$isGridScreen} + {#if !$isGridScreen && $dndParent} @@ -24,7 +24,7 @@ interface DNDTarget { parent: string empty: boolean acceptsChildren: boolean - node?: Node + element?: HTMLElement } interface DNDDrop { diff --git a/packages/client/src/utils/grid.ts b/packages/client/src/utils/grid.ts index 6294c70f55..c0e4bd5bfa 100644 --- a/packages/client/src/utils/grid.ts +++ b/packages/client/src/utils/grid.ts @@ -68,15 +68,18 @@ export const getGridVar = (device: string, param: string) => `--grid-${device}-${param}` // Determines whether a JS event originated from immediately within a grid -export const isGridEvent = (e: Event & { target: HTMLElement }): boolean => { +export const isGridEvent = (e: Event): boolean => { + if (!(e.target instanceof HTMLElement)) { + return false + } + const componentParent = e.target.closest?.(".component")?.parentNode as + | HTMLElement + | undefined + const gridDOMCandidate = componentParent?.closest(".component") + ?.childNodes[0] as HTMLElement | undefined return ( e.target.dataset?.indicator === "true" || - // @ts-expect-error: api is not properly typed - e.target - .closest?.(".component") - // @ts-expect-error - ?.parentNode.closest(".component") - ?.childNodes[0]?.classList?.contains("grid") + !!gridDOMCandidate?.classList?.contains("grid") ) } From 732b2575d1b499f61d638e8ea39427aaebeec9d3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 14:21:39 +0000 Subject: [PATCH 13/64] Type grid DND handler --- .../components/preview/GridDNDHandler.svelte | 124 ++++++++++++------ .../src/components/preview/Indicator.svelte | 6 +- packages/client/src/index.ts | 2 +- packages/client/src/utils/grid.ts | 39 +++--- packages/frontend-core/src/utils/memo.d.ts | 2 +- 5 files changed, 110 insertions(+), 63 deletions(-) diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index e2414e9d78..24d61bad2b 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -1,4 +1,4 @@ - {#if $dndIsDragging} @@ -14,14 +19,16 @@ /> {/if} - + {#if !waitingForGrid} + + {/if} {/if} From 61940705b94394005c9a634c93e5f891edce3be8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 16:01:45 +0000 Subject: [PATCH 15/64] Increase DND performance via minimzing component updates --- .../new/_components/NewComponentPanel.svelte | 3 +- .../src/components/preview/DNDHandler.svelte | 7 +- .../preview/DNDPlaceholderOverlay.svelte | 108 ------------------ .../preview/DNDSelectionIndicators.svelte | 10 +- .../components/preview/GridDNDHandler.svelte | 2 +- .../components/preview/IndicatorSet.svelte | 1 + packages/client/src/stores/dnd.ts | 17 +-- 7 files changed, 24 insertions(+), 124 deletions(-) delete mode 100644 packages/client/src/components/preview/DNDPlaceholderOverlay.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index f80b681782..d13d72b89f 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -261,8 +261,7 @@ class="component" class:selected={selectedIndex === orderMap[component.component]} on:click={() => addComponent(component.component)} - on:mouseover={() => (selectedIndex = null)} - on:focus + on:mouseenter={() => (selectedIndex = null)} > {component.name} diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index a0f9bfe2aa..15177a90c4 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -25,6 +25,7 @@ $: source = $dndStore.source $: target = $dndStore.target $: drop = $dndStore.drop + $: gridScreen = $isGridScreen // Local flag for whether we are awaiting an async drop event let dropping = false @@ -235,7 +236,7 @@ // Callback when on top of a component const onDragOver = (e: DragEvent) => { - if (!source || !target || $isGridScreen) { + if (!source || !target || gridScreen) { return } handleEvent(e) @@ -243,7 +244,7 @@ // Callback when entering a potential drop target const onDragEnter = async (e: DragEvent) => { - if (!source || $isGridScreen || !(e.target instanceof HTMLElement)) { + if (!source || gridScreen || !(e.target instanceof HTMLElement)) { return } @@ -278,7 +279,7 @@ source.type, drop.parent, drop.index, - $dndStore.source?.props + $dndStore.meta?.props ) dropping = false stopDragging() diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte deleted file mode 100644 index adff10baf8..0000000000 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte index d07082d439..cd7eb8302d 100644 --- a/packages/client/src/components/preview/DNDSelectionIndicators.svelte +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -1,12 +1,18 @@ {#if $dndIsDragging} diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 24d61bad2b..aa5187dec1 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -85,7 +85,7 @@ // real component to render in the new position before updating the DND // store, preventing the green DND overlay from being out of position if ($dndSource?.isNew && styles) { - dndStore.actions.updateSourceProps({ + dndStore.actions.updateNewComponentProps({ _styles: { normal: styles, }, diff --git a/packages/client/src/components/preview/IndicatorSet.svelte b/packages/client/src/components/preview/IndicatorSet.svelte index 4fc45e7b8a..83535f92cb 100644 --- a/packages/client/src/components/preview/IndicatorSet.svelte +++ b/packages/client/src/components/preview/IndicatorSet.svelte @@ -93,6 +93,7 @@ const observeMutations = (node: Node) => { mutationObserver.observe(node, { attributes: true, + attributeFilter: ["style"], }) observingMutations = true } diff --git a/packages/client/src/stores/dnd.ts b/packages/client/src/stores/dnd.ts index 6160d654da..c04ca9547e 100644 --- a/packages/client/src/stores/dnd.ts +++ b/packages/client/src/stores/dnd.ts @@ -16,7 +16,6 @@ interface DNDSource { icon?: string type: string isNew: boolean - props?: Record } interface DNDTarget { @@ -32,10 +31,15 @@ interface DNDDrop { index: number } +interface DNDMeta { + props?: Record +} + interface DNDState { source?: DNDSource target?: DNDTarget drop?: DNDDrop + meta?: DNDMeta } const createDndStore = () => { @@ -106,15 +110,12 @@ const createDndStore = () => { store.set({}) } - const updateSourceProps = (props: Record) => { + const updateNewComponentProps = (props: Record) => { store.update(state => { - if (!state.source) { - return state - } return { ...state, - source: { - ...state.source, + meta: { + ...state.meta, props, }, } @@ -129,7 +130,7 @@ const createDndStore = () => { updateTarget, updateDrop, reset, - updateSourceProps, + updateNewComponentProps, }, } } From b4fed6a02ffecb6b9a23cae7b30493902257b713 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 16:06:45 +0000 Subject: [PATCH 16/64] Cleanup --- .../preview/GridNewComponentDNDHandler.svelte | 166 ------------------ 1 file changed, 166 deletions(-) delete mode 100644 packages/client/src/components/preview/GridNewComponentDNDHandler.svelte diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte deleted file mode 100644 index a705561294..0000000000 --- a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte +++ /dev/null @@ -1,166 +0,0 @@ - From 585c9a8f6227dd1e9f5fbe47822fd5fba2571534 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 16:36:39 +0000 Subject: [PATCH 17/64] Support scrolling while dragging components --- .../src/components/preview/GridDNDHandler.svelte | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index aa5187dec1..e5297e9208 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -53,6 +53,7 @@ ghost.src = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" + let scrollElement: HTMLElement let dragInfo: GridDragInfo | undefined let styles = memo | undefined>() @@ -75,6 +76,8 @@ // Reset when not dragging new components $: !$dndIsDragging && stopDragging() + const scrollOffset = () => scrollElement?.scrollTop || 0 + const applyStyles = async ( instance: any, styles: Record | undefined @@ -113,7 +116,7 @@ } const diffX = mouseX - startX let deltaX = Math.round(diffX / colSize) - const diffY = mouseY - startY + const diffY = mouseY - startY + scrollOffset() let deltaY = Math.round(diffY / GridRowHeight) if (mode === GridDragMode.Move) { deltaX = minMax(deltaX, 1 - colStart, cols + 1 - colEnd) @@ -186,7 +189,7 @@ mode: GridDragMode.Move, grid: { startX: bounds.left + bounds.width / 2, - startY: bounds.top + bounds.height / 2, + startY: bounds.top + bounds.height / 2 + scrollOffset(), rowStart: parseInt(styles.gridRowStart), rowEnd: parseInt(styles.gridRowEnd), colStart: parseInt(styles.gridColumnStart), @@ -249,7 +252,7 @@ side, grid: { startX: e.clientX, - startY: e.clientY, + startY: e.clientY + scrollOffset(), rowStart: parseInt(styles.gridRowStart), rowEnd: parseInt(styles.gridRowEnd), colStart: parseInt(styles.gridColumnStart), @@ -295,12 +298,17 @@ } onMount(() => { + scrollElement = document.getElementsByClassName( + "screen-wrapper" + )[0] as HTMLElement document.addEventListener("dragstart", onDragStart, false) document.addEventListener("dragover", onDragOver, false) + document.addEventListener("scroll", processEvent) }) onDestroy(() => { document.removeEventListener("dragstart", onDragStart, false) document.removeEventListener("dragover", onDragOver, false) + document.removeEventListener("scroll", processEvent) }) From 33f286d528780db41bf29db076c4de390fc337f1 Mon Sep 17 00:00:00 2001 From: mikesealey Date: Tue, 11 Feb 2025 17:09:34 +0000 Subject: [PATCH 18/64] correctly types gen-collection-info.ts --- packages/string-templates/package.json | 1 + .../scripts/gen-collection-info.ts | 49 ++++++++++--------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index acd0ea4fa8..a80c2ec15c 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -33,6 +33,7 @@ "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-typescript": "8.3.0", + "@types/doctrine": "^0.0.9", "doctrine": "^3.0.0", "jest": "29.7.0", "marked": "^4.0.10", diff --git a/packages/string-templates/scripts/gen-collection-info.ts b/packages/string-templates/scripts/gen-collection-info.ts index 8b3825bf5c..ff26228ea9 100644 --- a/packages/string-templates/scripts/gen-collection-info.ts +++ b/packages/string-templates/scripts/gen-collection-info.ts @@ -7,18 +7,30 @@ import { marked } from "marked" import { join, dirname } from "path" const helpers = require("@budibase/handlebars-helpers") -const doctrine = require("doctrine") +import doctrine, { Annotation } from "doctrine" -type HelperInfo = { +type BudibaseAnnotation = Annotation & { + example?: string acceptsInline?: boolean acceptsBlock?: boolean +} + +type Helper = { + args: string[] + numArgs: number example?: string description: string - tags?: any[] + requiresBlock?: boolean +} + +type Manifest = { + [category: string]: { + [helper: string]: Helper + } } const FILENAME = join(__dirname, "..", "src", "manifest.json") -const outputJSON: any = {} +const outputJSON: Manifest = {} const ADDED_HELPERS = { date: { date: { @@ -38,11 +50,11 @@ const ADDED_HELPERS = { }, } -function fixSpecialCases(name: string, obj: any) { +function fixSpecialCases(name: string, obj: Helper) { const args = obj.args if (name === "ifNth") { - args[0] = "a" - args[1] = "b" + obj.args = ["a", "b", "options"] + obj.numArgs = 3 } if (name === "eachIndex") { obj.description = "Iterates the array, listing an item and the index of it." @@ -66,10 +78,10 @@ function lookForward(lines: string[], funcLines: string[], idx: number) { return true } -function getCommentInfo(file: string, func: string): HelperInfo { +function getCommentInfo(file: string, func: string): BudibaseAnnotation { const lines = file.split("\n") const funcLines = func.split("\n") - let comment = null + let comment: string | null = null for (let idx = 0; idx < lines.length; ++idx) { // from here work back until we have the comment if (lookForward(lines, funcLines, idx)) { @@ -91,15 +103,9 @@ function getCommentInfo(file: string, func: string): HelperInfo { } } if (comment == null) { - return { description: "" } + return { description: "", tags: [] } } - const docs: { - acceptsInline?: boolean - acceptsBlock?: boolean - example: string - description: string - tags: any[] - } = doctrine.parse(comment, { unwrap: true }) + const docs: BudibaseAnnotation = doctrine.parse(comment, { unwrap: true }) // some hacky fixes docs.description = docs.description.replace(/\n/g, " ") docs.description = docs.description.replace(/[ ]{2,}/g, " ") @@ -135,7 +141,7 @@ function run() { )}/lib/${collection}.js`, "utf8" ) - const collectionInfo: any = {} + const collectionInfo: { [name: string]: Helper } = {} // collect information about helper let hbsHelperInfo = helpers[collection]() for (let entry of Object.entries(hbsHelperInfo)) { @@ -154,11 +160,8 @@ function run() { const jsDocInfo = getCommentInfo(collectionFile, fnc) let args = jsDocInfo.tags .filter(tag => tag.title === "param") - .map( - tag => - tag.description && - tag.description.replace(/`/g, "").split(" ")[0].trim() - ) + .filter(tag => tag.description) + .map(tag => tag.description!.replace(/`/g, "").split(" ")[0].trim()) collectionInfo[name] = fixSpecialCases(name, { args, numArgs: args.length, From 6f3d097410551cb163459d77ae880a604189ffe3 Mon Sep 17 00:00:00 2001 From: mikesealey Date: Tue, 11 Feb 2025 17:21:05 +0000 Subject: [PATCH 19/64] adds yarn lock --- yarn.lock | 228 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 175 insertions(+), 53 deletions(-) diff --git a/yarn.lock b/yarn.lock index ea7084e53a..71dbfa2c63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -810,7 +810,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@4.2.1", "@azure/identity@^4.2.1": +"@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2130,28 +2130,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.47" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.47.tgz#150d7b16b14932d03c84bdb0e6d570d490c28a5c" - integrity sha512-UeTIq7yzMUK6w/akUsRafoD/Kif6PXv4d7K1arn8GTMjwFm9QYu2hg1YkQ+duNdwyZ/GEPlEAV5SYK+NDgtpdA== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "*" - "@budibase/shared-core" "*" - "@budibase/string-templates" "*" - "@budibase/types" "*" - "@koa/router" "13.1.0" - bull "4.10.1" - dd-trace "5.26.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - "@budibase/vm-browserify@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@budibase/vm-browserify/-/vm-browserify-1.1.4.tgz#eecb001bd9521cb7647e26fb4d2d29d0a4dce262" @@ -5417,6 +5395,11 @@ "@types/node" "*" "@types/ssh2" "*" +"@types/doctrine@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.9.tgz#d86a5f452a15e3e3113b99e39616a9baa0f9863f" + integrity sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA== + "@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.1": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -7049,7 +7032,23 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -10667,7 +10666,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.15.6: +follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -11282,10 +11281,22 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@15.13.0, globals@^11.1.0, globals@^13.19.0, globals@^14.0.0: - version "15.13.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-15.13.0.tgz#bbec719d69aafef188ecd67954aae76a696010fc" - integrity sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g== +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== globalthis@^1.0.1, globalthis@^1.0.4: version "1.0.4" @@ -11695,7 +11706,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -11807,6 +11823,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +husky@^9.1.4: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -12151,6 +12172,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12590,11 +12616,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13474,7 +13495,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -14879,7 +14907,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15072,13 +15100,27 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -16102,7 +16144,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -17087,6 +17137,13 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +psl@^1.1.28: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -17120,6 +17177,11 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + pupa@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" @@ -17951,6 +18013,11 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== +sax@>=0.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== + sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -18023,13 +18090,28 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: +"semver@2 || 3 || 4 || 5", semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -18658,7 +18740,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18750,7 +18841,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18764,6 +18855,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -19477,7 +19575,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -19487,6 +19585,14 @@ tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0 universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -19954,14 +20060,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20511,7 +20609,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20529,6 +20627,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -20656,7 +20763,14 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: +xml2js@0.1.x: + version "0.1.14" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" + integrity sha512-pbdws4PPPNc1HPluSUKamY4GWMk592K7qwcj6BExbVOhhubub8+pMda/ql68b6L3luZs/OGjGSB5goV7SnmgnA== + dependencies: + sax ">=0.1.1" + +xml2js@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -20664,6 +20778,14 @@ xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: sax ">=0.6.0" xmlbuilder "~11.0.0" +xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From 097f67250ced8558d0c9476c00b6df7e24e4da51 Mon Sep 17 00:00:00 2001 From: mikesealey Date: Wed, 12 Feb 2025 10:19:14 +0000 Subject: [PATCH 20/64] fixes lint issue --- packages/string-templates/scripts/gen-collection-info.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/string-templates/scripts/gen-collection-info.ts b/packages/string-templates/scripts/gen-collection-info.ts index ff26228ea9..f7df88ee85 100644 --- a/packages/string-templates/scripts/gen-collection-info.ts +++ b/packages/string-templates/scripts/gen-collection-info.ts @@ -51,7 +51,6 @@ const ADDED_HELPERS = { } function fixSpecialCases(name: string, obj: Helper) { - const args = obj.args if (name === "ifNth") { obj.args = ["a", "b", "options"] obj.numArgs = 3 From b1507c275650ad6ec2b7e634ed64377990d25470 Mon Sep 17 00:00:00 2001 From: mikesealey Date: Wed, 12 Feb 2025 10:54:48 +0000 Subject: [PATCH 21/64] updates yarn.lock --- yarn.lock | 187 +++++++++++++++--------------------------------------- 1 file changed, 50 insertions(+), 137 deletions(-) diff --git a/yarn.lock b/yarn.lock index 71dbfa2c63..e9138b2810 100644 --- a/yarn.lock +++ b/yarn.lock @@ -810,7 +810,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@^4.2.1": +"@azure/identity@4.2.1", "@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2130,6 +2130,28 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" +"@budibase/pro@npm:@budibase/pro@latest": + version "3.4.6" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.4.6.tgz#62b6ee13a015b98d4768dc7821f468f8177da3e9" + integrity sha512-MC3P5SMokmqbjejZMlNM6z7NB9o5H6hZ++yVvbyThniBPYfuDc2ssa1HNwwcuNE3uRLhcxcKe8CY/0SbFgn51g== + dependencies: + "@anthropic-ai/sdk" "^0.27.3" + "@budibase/backend-core" "*" + "@budibase/shared-core" "*" + "@budibase/string-templates" "*" + "@budibase/types" "*" + "@koa/router" "13.1.0" + bull "4.10.1" + dd-trace "5.26.0" + joi "17.6.0" + jsonwebtoken "9.0.2" + lru-cache "^7.14.1" + memorystream "^0.3.1" + node-fetch "2.6.7" + openai "4.59.0" + scim-patch "^0.8.1" + scim2-parse-filter "^0.2.8" + "@budibase/vm-browserify@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@budibase/vm-browserify/-/vm-browserify-1.1.4.tgz#eecb001bd9521cb7647e26fb4d2d29d0a4dce262" @@ -7032,23 +7054,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axios@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -10666,7 +10672,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: +follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -11281,22 +11287,10 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globals@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" - integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== +globals@15.13.0, globals@^11.1.0, globals@^13.19.0, globals@^14.0.0: + version "15.13.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.13.0.tgz#bbec719d69aafef188ecd67954aae76a696010fc" + integrity sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g== globalthis@^1.0.1, globalthis@^1.0.4: version "1.0.4" @@ -11706,12 +11700,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12172,11 +12161,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12616,6 +12600,11 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13495,14 +13484,7 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@^3.0.2, kind-of@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -14907,7 +14889,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@^1.5.2: +msgpackr@1.10.1, msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15100,27 +15082,13 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.6.9: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -16144,15 +16112,7 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -passport@^0.6.0: +passport@0.6.0, passport@^0.4.0, passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -17137,13 +17097,6 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== -psl@^1.1.28: - version "1.15.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" - integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== - dependencies: - punycode "^2.3.1" - psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -17177,11 +17130,6 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -punycode@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - pupa@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" @@ -18013,11 +17961,6 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== -sax@>=0.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" - integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== - sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -18090,28 +18033,13 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.6.0, semver@^5.7.1: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== - seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -19575,7 +19503,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -19585,14 +19513,6 @@ touch@^3.1.0: universalify "^0.2.0" url-parse "^1.5.3" -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -20060,6 +19980,14 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" + integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== + dependencies: + has-value "^2.0.2" + isobject "^4.0.0" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20763,14 +20691,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.1.x: - version "0.1.14" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" - integrity sha512-pbdws4PPPNc1HPluSUKamY4GWMk592K7qwcj6BExbVOhhubub8+pMda/ql68b6L3luZs/OGjGSB5goV7SnmgnA== - dependencies: - sax ">=0.1.1" - -xml2js@0.6.2: +xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -20778,14 +20699,6 @@ xml2js@0.6.2: sax ">=0.6.0" xmlbuilder "~11.0.0" -xml2js@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From e7342c1d406d1ecdeb7edd0c6c091c34afaea05b Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 12 Feb 2025 11:53:09 +0000 Subject: [PATCH 22/64] Update yarn.lock. --- yarn.lock | 5 ----- 1 file changed, 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0f348710b6..d03bba5238 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12864,11 +12864,6 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== -husky@^9.1.4: - version "9.1.7" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" - integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== - ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" From 39d382f2c2c1de7ca2be40593f87ddca0cf7857d Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 17:40:34 +0100 Subject: [PATCH 23/64] Type inputs --- .../src/components/common/CodeEditor/CodeEditor.svelte | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index bc88f0f981..3271bd4ad2 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -10,6 +10,7 @@ closeBracketsKeymap, acceptCompletion, completionStatus, + CompletionContext, } from "@codemirror/autocomplete" import { lineNumbers, @@ -44,11 +45,15 @@ import { javascript } from "@codemirror/lang-javascript" import { EditorModes } from "./" import { themeStore } from "@/stores/portal" - import type { EditorMode } from "@budibase/types" + import type { BindingCompletion, EditorMode } from "@budibase/types" export let label: string | undefined = undefined // TODO: work out what best type fits this - export let completions: any[] = [] + export let completions: ((context: CompletionContext) => Promise<{ + from: number + filter: boolean + options: BindingCompletion[] + } | null>)[] = [] export let mode: EditorMode = EditorModes.Handlebars export let value: string | null = "" export let placeholder: string | null = null From dec7cb97a87bbf98c9968ea4578a1b57a4ea2620 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 17:41:58 +0100 Subject: [PATCH 24/64] Split field and helpers --- .../src/components/common/CodeEditor/index.ts | 19 +++++++++++++++++++ .../common/bindings/BindingPanel.svelte | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 0c974e0bf4..4f0cb76861 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -217,6 +217,25 @@ export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => { return coreCompletion } +export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { + async function coreCompletion(context: CompletionContext) { + let jsBinding = context.matchBefore(/\bhelpers\./) + let options = baseCompletions || [] + + if (jsBinding) { + return { + from: jsBinding.from + (jsBinding.to - jsBinding.from), + filter: false, + options, + } + } + + return null + } + + return coreCompletion +} + export const buildBindingInfoNode = ( completion: BindingCompletion, binding: any diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index ffb477012c..6fea2baccf 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -23,6 +23,7 @@ snippetAutoComplete, EditorModes, bindingsToCompletions, + jsHelperAutocomplete, } from "../CodeEditor" import BindingSidePanel from "./BindingSidePanel.svelte" import EvaluationSidePanel from "./EvaluationSidePanel.svelte" @@ -114,10 +115,8 @@ useSnippets?: boolean ) => { const completions: ((_: CompletionContext) => any)[] = [ - jsAutocomplete([ - ...bindingCompletions, - ...getHelperCompletions(EditorModes.JS), - ]), + jsAutocomplete([...bindingCompletions.filter(c => c.label)]), + jsHelperAutocomplete([...getHelperCompletions(EditorModes.JS)]), ] if (useSnippets && snippets) { completions.push(snippetAutoComplete(snippets)) From d42832e22302aa5b3eb74b97fe724fcebd015ad0 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 17:51:50 +0100 Subject: [PATCH 25/64] Increase builder ts target --- packages/builder/tsconfig.build.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/builder/tsconfig.build.json b/packages/builder/tsconfig.build.json index 119fe56c81..77606ef8ed 100644 --- a/packages/builder/tsconfig.build.json +++ b/packages/builder/tsconfig.build.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig.build.json", "compilerOptions": { + "target": "es2018", "allowJs": true }, "include": ["./src/**/*"], From 203647d7ec6d404c38e5eaa8d99dc8aadccb6523 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 17:51:59 +0100 Subject: [PATCH 26/64] Filter helpers --- .../src/components/common/CodeEditor/index.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 4f0cb76861..32e7250b23 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -219,14 +219,20 @@ export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => { export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { async function coreCompletion(context: CompletionContext) { - let jsBinding = context.matchBefore(/\bhelpers\./) + let jsBinding = context.matchBefore(/\bhelpers\.\w*/) let options = baseCompletions || [] if (jsBinding) { + const match = jsBinding.text.match(/\bhelpers\.(?\w*)/) + if (!match) { + return null + } + const query = match.groups?.["helper"] || "" + let filtered = bindingFilter(options, query) return { - from: jsBinding.from + (jsBinding.to - jsBinding.from), + from: jsBinding.from + match[0].length, filter: false, - options, + options: filtered, } } From 8c88593eb44707c21b425bf9020d07daed8098b3 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 18:09:44 +0100 Subject: [PATCH 27/64] Fix completion --- .../common/CodeEditor/CodeEditor.svelte | 1 - .../src/components/common/CodeEditor/index.ts | 30 ++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index 3271bd4ad2..941cf7a6b1 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -51,7 +51,6 @@ // TODO: work out what best type fits this export let completions: ((context: CompletionContext) => Promise<{ from: number - filter: boolean options: BindingCompletion[] } | null>)[] = [] export let mode: EditorMode = EditorModes.Handlebars diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 32e7250b23..478bad28a3 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -103,11 +103,11 @@ export const helpersToCompletion = ( detail: "Function", apply: ( view: any, - completion: BindingCompletion, + _completion: BindingCompletion, from: number, to: number ) => { - insertBinding(view, from, to, helperName, mode) + insertBinding(view, from, to, helperName, mode, AutocompleteType.HELPER) }, } }) @@ -230,7 +230,8 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { const query = match.groups?.["helper"] || "" let filtered = bindingFilter(options, query) return { - from: jsBinding.from + match[0].length, + from: jsBinding.from, + to: jsBinding.from + match[0].length, filter: false, options: filtered, } @@ -243,7 +244,7 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { } export const buildBindingInfoNode = ( - completion: BindingCompletion, + _completion: BindingCompletion, binding: any ) => { if (!binding.valueHTML || binding.value == null) { @@ -303,18 +304,26 @@ export function jsInsert( return parsedInsert } +const enum AutocompleteType { + BINDING, + HELPER, +} + // Autocomplete apply behaviour export const insertBinding = ( view: any, from: number, to: number, text: string, - mode: { name: "javascript" | "handlebars" } + mode: { name: "javascript" | "handlebars" }, + type: AutocompleteType ) => { let parsedInsert if (mode.name == "javascript") { - parsedInsert = jsInsert(view.state.doc?.toString(), from, to, text) + parsedInsert = jsInsert(view.state.doc?.toString(), from, to, text, { + helper: type === AutocompleteType.HELPER, + }) } else if (mode.name == "handlebars") { parsedInsert = hbInsert(view.state.doc?.toString(), from, to, text) } else { @@ -412,7 +421,14 @@ export const bindingsToCompletions = ( from: number, to: number ) => { - insertBinding(view, from, to, binding.readableBinding, mode) + insertBinding( + view, + from, + to, + binding.readableBinding, + mode, + AutocompleteType.BINDING + ) }, }) return acc From 4619742a5725e0b8d2dd4435653ac4e0f634e61c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 19:54:06 +0100 Subject: [PATCH 28/64] Clean --- .../builder/src/components/common/bindings/BindingPanel.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 6fea2baccf..3babc395e6 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -115,7 +115,7 @@ useSnippets?: boolean ) => { const completions: ((_: CompletionContext) => any)[] = [ - jsAutocomplete([...bindingCompletions.filter(c => c.label)]), + jsAutocomplete([...bindingCompletions]), jsHelperAutocomplete([...getHelperCompletions(EditorModes.JS)]), ] if (useSnippets && snippets) { From 1d3c2d33bf0e8cfc67960d97bdaae5ef62a02054 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 20:05:03 +0100 Subject: [PATCH 29/64] Add helper to create keyword --- .../src/components/common/CodeEditor/index.ts | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 478bad28a3..ced07edd1f 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -92,7 +92,7 @@ export const helpersToCompletion = ( const helperSection = buildSectionHeader(type, sectionName, icon, 99) return Object.keys(helpers).flatMap(helperName => { - let helper = helpers[helperName] + const helper = helpers[helperName] return { label: helperName, info: (completion: BindingCompletion) => { @@ -220,9 +220,9 @@ export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => { export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { async function coreCompletion(context: CompletionContext) { let jsBinding = context.matchBefore(/\bhelpers\.\w*/) - let options = baseCompletions || [] if (jsBinding) { + let options = baseCompletions || [] const match = jsBinding.text.match(/\bhelpers\.(?\w*)/) if (!match) { return null @@ -235,6 +235,36 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { filter: false, options: filtered, } + } else { + const prefix = context.matchBefore(/\b\w+/) + if (prefix && "helpers.".startsWith(prefix.text)) { + return { + from: context.pos - prefix.text.length, + to: context.pos, + filter: false, + options: [ + { + label: "helpers.", + detail: "Helpers utilities", + apply: ( + view: any, + _completion: BindingCompletion, + from: number, + to: number + ) => { + insertBinding( + view, + from, + to, + "helpers.", + EditorModes.JS, + AutocompleteType.TEXT + ) + }, + }, + ], + } + } } return null @@ -307,6 +337,7 @@ export function jsInsert( const enum AutocompleteType { BINDING, HELPER, + TEXT, } // Autocomplete apply behaviour @@ -323,6 +354,7 @@ export const insertBinding = ( if (mode.name == "javascript") { parsedInsert = jsInsert(view.state.doc?.toString(), from, to, text, { helper: type === AutocompleteType.HELPER, + disableWrapping: type === AutocompleteType.TEXT, }) } else if (mode.name == "handlebars") { parsedInsert = hbInsert(view.state.doc?.toString(), from, to, text) From b49c74e37b9f682b72b8d4f9761fc64a38c7bf2f Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 20:15:45 +0100 Subject: [PATCH 30/64] Chain it --- .../src/components/common/CodeEditor/index.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index ced07edd1f..06e1cc8b68 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -7,7 +7,8 @@ import { Helper, Snippet, } from "@budibase/types" -import { CompletionContext } from "@codemirror/autocomplete" +import { CompletionContext, startCompletion } from "@codemirror/autocomplete" +import { EditorView } from "@codemirror/view" export const EditorModes: EditorModesMap = { JS: { @@ -102,7 +103,7 @@ export const helpersToCompletion = ( section: helperSection, detail: "Function", apply: ( - view: any, + view: EditorView, _completion: BindingCompletion, from: number, to: number @@ -139,7 +140,7 @@ export const snippetAutoComplete = (snippets: Snippet[]) => { type: "text", simple: true, apply: ( - view: any, + view: EditorView, completion: BindingCompletion, from: number, to: number @@ -247,7 +248,7 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { label: "helpers.", detail: "Helpers utilities", apply: ( - view: any, + view: EditorView, _completion: BindingCompletion, from: number, to: number @@ -260,6 +261,9 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { EditorModes.JS, AutocompleteType.TEXT ) + + // Trigger again the completion, to chain it with the helpers completion + startCompletion(view) }, }, ], @@ -342,7 +346,7 @@ const enum AutocompleteType { // Autocomplete apply behaviour export const insertBinding = ( - view: any, + view: EditorView, from: number, to: number, text: string, @@ -386,7 +390,7 @@ export const insertBinding = ( } export const insertSnippet = ( - view: any, + view: EditorView, from: number, to: number, text: string @@ -448,8 +452,8 @@ export const bindingsToCompletions = ( detail: displayType, section: bindingSectionHeader, apply: ( - view: any, - completion: BindingCompletion, + view: EditorView, + _completion: BindingCompletion, from: number, to: number ) => { From a362ab51202a4fe137e531bb6c7058241b5b3615 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 20:20:55 +0100 Subject: [PATCH 31/64] Simplify --- packages/builder/src/components/common/CodeEditor/index.ts | 3 ++- packages/types/src/ui/bindings/binding.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 06e1cc8b68..e9f554c44f 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -246,7 +246,8 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { options: [ { label: "helpers.", - detail: "Helpers utilities", + type: "text", + simple: true, apply: ( view: EditorView, _completion: BindingCompletion, diff --git a/packages/types/src/ui/bindings/binding.ts b/packages/types/src/ui/bindings/binding.ts index a770a25a3e..dfcd3c6a6d 100644 --- a/packages/types/src/ui/bindings/binding.ts +++ b/packages/types/src/ui/bindings/binding.ts @@ -3,6 +3,7 @@ export interface BindingCompletion { name: string } label: string + simple?: boolean } export interface EnrichedBinding { From 5f13c7e5c55d5d4622f9f2acc5057d54a997bc21 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 20:33:16 +0100 Subject: [PATCH 32/64] Don't show snipopets on $("") autocomplete --- packages/builder/src/components/common/CodeEditor/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index e9f554c44f..3a2d9624a6 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -129,6 +129,13 @@ export const snippetAutoComplete = (snippets: Snippet[]) => { if (!snippets?.length) { return null } + + let jsBinding = context.matchBefore(/\$\("[\s\w]*/) + if (jsBinding) { + // We are handing a js field completion + return null + } + const word = context.matchBefore(/\w*/) if (!word || (word.from == word.to && !context.explicit)) { return null From f08a2af4bc791340b79cb9e34401bfb36bbb5389 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 20:34:14 +0100 Subject: [PATCH 33/64] Check boundaries --- packages/builder/src/components/common/CodeEditor/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 3a2d9624a6..a750ca52a1 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -136,7 +136,7 @@ export const snippetAutoComplete = (snippets: Snippet[]) => { return null } - const word = context.matchBefore(/\w*/) + const word = context.matchBefore(/\b\w*/) if (!word || (word.from == word.to && !context.explicit)) { return null } From 4c8ca259cfdfa7dc7f6ab25f680d2f297bf62852 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 10 Feb 2025 22:50:44 +0100 Subject: [PATCH 34/64] Fix --- .../builder/src/components/common/CodeEditor/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index a750ca52a1..5675ba2968 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -130,8 +130,7 @@ export const snippetAutoComplete = (snippets: Snippet[]) => { return null } - let jsBinding = context.matchBefore(/\$\("[\s\w]*/) - if (jsBinding) { + if (context.matchBefore(/\$\("[\s\w]*/)) { // We are handing a js field completion return null } @@ -227,6 +226,11 @@ export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => { export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { async function coreCompletion(context: CompletionContext) { + if (context.matchBefore(/\$\("[\s\w]*/)) { + // We are handing a js field completion + return null + } + let jsBinding = context.matchBefore(/\bhelpers\.\w*/) if (jsBinding) { From 3e2f255f83883f0b4fc64e6ac39964443217d659 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 10:45:51 +0100 Subject: [PATCH 35/64] Renames --- .../common/CodeEditor/CodeEditor.svelte | 4 +-- .../src/components/common/CodeEditor/index.ts | 26 ++++++++++--------- .../common/bindings/BindingPanel.svelte | 6 ++--- packages/types/src/ui/bindings/binding.ts | 2 +- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index 941cf7a6b1..4096f4d608 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -45,13 +45,13 @@ import { javascript } from "@codemirror/lang-javascript" import { EditorModes } from "./" import { themeStore } from "@/stores/portal" - import type { BindingCompletion, EditorMode } from "@budibase/types" + import type { BindingCompletionOption, EditorMode } from "@budibase/types" export let label: string | undefined = undefined // TODO: work out what best type fits this export let completions: ((context: CompletionContext) => Promise<{ from: number - options: BindingCompletion[] + options: BindingCompletionOption[] } | null>)[] = [] export let mode: EditorMode = EditorModes.Handlebars export let value: string | null = "" diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 5675ba2968..bd22677c10 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -2,7 +2,7 @@ import { getManifest } from "@budibase/string-templates" import sanitizeHtml from "sanitize-html" import { groupBy } from "lodash" import { - BindingCompletion, + BindingCompletionOption, EditorModesMap, Helper, Snippet, @@ -96,7 +96,7 @@ export const helpersToCompletion = ( const helper = helpers[helperName] return { label: helperName, - info: (completion: BindingCompletion) => { + info: (completion: BindingCompletionOption) => { return buildHelperInfoNode(completion, helper) }, type: "helper", @@ -104,7 +104,7 @@ export const helpersToCompletion = ( detail: "Function", apply: ( view: EditorView, - _completion: BindingCompletion, + _completion: BindingCompletionOption, from: number, to: number ) => { @@ -147,7 +147,7 @@ export const snippetAutoComplete = (snippets: Snippet[]) => { simple: true, apply: ( view: EditorView, - completion: BindingCompletion, + completion: BindingCompletionOption, from: number, to: number ) => { @@ -158,7 +158,7 @@ export const snippetAutoComplete = (snippets: Snippet[]) => { } } -const bindingFilter = (options: BindingCompletion[], query: string) => { +const bindingFilter = (options: BindingCompletionOption[], query: string) => { return options.filter(completion => { const section_parsed = completion.section.name.toLowerCase() const label_parsed = completion.label.toLowerCase() @@ -171,7 +171,7 @@ const bindingFilter = (options: BindingCompletion[], query: string) => { }) } -export const hbAutocomplete = (baseCompletions: BindingCompletion[]) => { +export const hbAutocomplete = (baseCompletions: BindingCompletionOption[]) => { async function coreCompletion(context: CompletionContext) { let bindingStart = context.matchBefore(EditorModes.Handlebars.match) @@ -198,7 +198,7 @@ export const hbAutocomplete = (baseCompletions: BindingCompletion[]) => { return coreCompletion } -export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => { +export const jsAutocomplete = (baseCompletions: BindingCompletionOption[]) => { async function coreCompletion(context: CompletionContext) { let jsBinding = context.matchBefore(/\$\("[\s\w]*/) let options = baseCompletions || [] @@ -224,7 +224,9 @@ export const jsAutocomplete = (baseCompletions: BindingCompletion[]) => { return coreCompletion } -export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { +export const jsHelperAutocomplete = ( + baseCompletions: BindingCompletionOption[] +) => { async function coreCompletion(context: CompletionContext) { if (context.matchBefore(/\$\("[\s\w]*/)) { // We are handing a js field completion @@ -261,7 +263,7 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { simple: true, apply: ( view: EditorView, - _completion: BindingCompletion, + _completion: BindingCompletionOption, from: number, to: number ) => { @@ -290,7 +292,7 @@ export const jsHelperAutocomplete = (baseCompletions: BindingCompletion[]) => { } export const buildBindingInfoNode = ( - _completion: BindingCompletion, + _completion: BindingCompletionOption, binding: any ) => { if (!binding.valueHTML || binding.value == null) { @@ -457,7 +459,7 @@ export const bindingsToCompletions = ( acc.push({ label: binding.display?.name || binding.readableBinding || "NO NAME", - info: (completion: BindingCompletion) => { + info: (completion: BindingCompletionOption) => { return buildBindingInfoNode(completion, binding) }, type: "binding", @@ -465,7 +467,7 @@ export const bindingsToCompletions = ( section: bindingSectionHeader, apply: ( view: EditorView, - _completion: BindingCompletion, + _completion: BindingCompletionOption, from: number, to: number ) => { diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 3babc395e6..ae2c701e92 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -35,7 +35,7 @@ import { BindingMode, SidePanel } from "@budibase/types" import type { EnrichedBinding, - BindingCompletion, + BindingCompletionOption, Snippet, Helper, CaretPositionFn, @@ -100,7 +100,7 @@ } } - const getHBSCompletions = (bindingCompletions: BindingCompletion[]) => { + const getHBSCompletions = (bindingCompletions: BindingCompletionOption[]) => { return [ hbAutocomplete([ ...bindingCompletions, @@ -110,7 +110,7 @@ } const getJSCompletions = ( - bindingCompletions: BindingCompletion[], + bindingCompletions: BindingCompletionOption[], snippets: Snippet[] | null, useSnippets?: boolean ) => { diff --git a/packages/types/src/ui/bindings/binding.ts b/packages/types/src/ui/bindings/binding.ts index dfcd3c6a6d..17141b5567 100644 --- a/packages/types/src/ui/bindings/binding.ts +++ b/packages/types/src/ui/bindings/binding.ts @@ -1,4 +1,4 @@ -export interface BindingCompletion { +export interface BindingCompletionOption { section: { name: string } From 237b1fc9b93bf4d1d8935606200a60d24364a231 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 10:48:28 +0100 Subject: [PATCH 36/64] Create types --- .../src/components/common/CodeEditor/CodeEditor.svelte | 8 +++----- .../builder/src/components/common/CodeEditor/index.ts | 9 ++++++--- .../src/components/common/bindings/BindingPanel.svelte | 4 ++-- packages/builder/src/types/bindings.ts | 7 +++++++ packages/builder/src/types/index.ts | 1 + 5 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 packages/builder/src/types/bindings.ts create mode 100644 packages/builder/src/types/index.ts diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index 4096f4d608..495862d1b8 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -45,14 +45,12 @@ import { javascript } from "@codemirror/lang-javascript" import { EditorModes } from "./" import { themeStore } from "@/stores/portal" - import type { BindingCompletionOption, EditorMode } from "@budibase/types" + import type { EditorMode } from "@budibase/types" + import { BindingCompletion } from "@/types" export let label: string | undefined = undefined // TODO: work out what best type fits this - export let completions: ((context: CompletionContext) => Promise<{ - from: number - options: BindingCompletionOption[] - } | null>)[] = [] + export let completions: BindingCompletion[] = [] export let mode: EditorMode = EditorModes.Handlebars export let value: string | null = "" export let placeholder: string | null = null diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index bd22677c10..65a432b0ae 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -9,6 +9,7 @@ import { } from "@budibase/types" import { CompletionContext, startCompletion } from "@codemirror/autocomplete" import { EditorView } from "@codemirror/view" +import { BindingCompletion } from "@/types" export const EditorModes: EditorModesMap = { JS: { @@ -124,7 +125,7 @@ export const getHelperCompletions = (mode: { }) } -export const snippetAutoComplete = (snippets: Snippet[]) => { +export const snippetAutoComplete = (snippets: Snippet[]): BindingCompletion => { return function myCompletions(context: CompletionContext) { if (!snippets?.length) { return null @@ -198,7 +199,9 @@ export const hbAutocomplete = (baseCompletions: BindingCompletionOption[]) => { return coreCompletion } -export const jsAutocomplete = (baseCompletions: BindingCompletionOption[]) => { +export const jsAutocomplete = ( + baseCompletions: BindingCompletionOption[] +): BindingCompletion => { async function coreCompletion(context: CompletionContext) { let jsBinding = context.matchBefore(/\$\("[\s\w]*/) let options = baseCompletions || [] @@ -226,7 +229,7 @@ export const jsAutocomplete = (baseCompletions: BindingCompletionOption[]) => { export const jsHelperAutocomplete = ( baseCompletions: BindingCompletionOption[] -) => { +): BindingCompletion => { async function coreCompletion(context: CompletionContext) { if (context.matchBefore(/\$\("[\s\w]*/)) { // We are handing a js field completion diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index ae2c701e92..98b1910e5c 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -43,7 +43,7 @@ JSONValue, } from "@budibase/types" import type { Log } from "@budibase/string-templates" - import type { CompletionContext } from "@codemirror/autocomplete" + import { BindingCompletion } from "@/types" const dispatch = createEventDispatcher() @@ -114,7 +114,7 @@ snippets: Snippet[] | null, useSnippets?: boolean ) => { - const completions: ((_: CompletionContext) => any)[] = [ + const completions: BindingCompletion[] = [ jsAutocomplete([...bindingCompletions]), jsHelperAutocomplete([...getHelperCompletions(EditorModes.JS)]), ] diff --git a/packages/builder/src/types/bindings.ts b/packages/builder/src/types/bindings.ts new file mode 100644 index 0000000000..ff1b08fb36 --- /dev/null +++ b/packages/builder/src/types/bindings.ts @@ -0,0 +1,7 @@ +import { BindingCompletionOption } from "@budibase/types" +import { CompletionContext } from "@codemirror/autocomplete" + +export type BindingCompletion = (context: CompletionContext) => Promise<{ + from: number + options: BindingCompletionOption[] +} | null> diff --git a/packages/builder/src/types/index.ts b/packages/builder/src/types/index.ts new file mode 100644 index 0000000000..f280d975b4 --- /dev/null +++ b/packages/builder/src/types/index.ts @@ -0,0 +1 @@ +export * from "./bindings" From 8fdc787080c256418bd5091f102c054d09173803 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 12:51:13 +0100 Subject: [PATCH 37/64] Typing --- .../src/components/common/CodeEditor/index.ts | 18 ++++++++++-------- packages/builder/src/types/bindings.ts | 4 ++-- packages/types/src/ui/bindings/binding.ts | 4 +++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 65a432b0ae..a1af4710de 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -89,7 +89,7 @@ export const buildSectionHeader = ( export const helpersToCompletion = ( helpers: Record, mode: { name: "javascript" | "handlebars" } -) => { +): BindingCompletionOption[] => { const { type, name: sectionName, icon } = SECTIONS.HB_HELPER const helperSection = buildSectionHeader(type, sectionName, icon, 99) @@ -117,7 +117,7 @@ export const helpersToCompletion = ( export const getHelperCompletions = (mode: { name: "javascript" | "handlebars" -}) => { +}): BindingCompletionOption[] => { // TODO: manifest needs to be properly typed const manifest: any = getManifest() return Object.keys(manifest).flatMap(key => { @@ -161,19 +161,21 @@ export const snippetAutoComplete = (snippets: Snippet[]): BindingCompletion => { const bindingFilter = (options: BindingCompletionOption[], query: string) => { return options.filter(completion => { - const section_parsed = completion.section.name.toLowerCase() + const section_parsed = completion.section?.name.toLowerCase() const label_parsed = completion.label.toLowerCase() const query_parsed = query.toLowerCase() return ( - section_parsed.includes(query_parsed) || + section_parsed?.includes(query_parsed) || label_parsed.includes(query_parsed) ) }) } -export const hbAutocomplete = (baseCompletions: BindingCompletionOption[]) => { - async function coreCompletion(context: CompletionContext) { +export const hbAutocomplete = ( + baseCompletions: BindingCompletionOption[] +): BindingCompletion => { + function coreCompletion(context: CompletionContext) { let bindingStart = context.matchBefore(EditorModes.Handlebars.match) let options = baseCompletions || [] @@ -202,7 +204,7 @@ export const hbAutocomplete = (baseCompletions: BindingCompletionOption[]) => { export const jsAutocomplete = ( baseCompletions: BindingCompletionOption[] ): BindingCompletion => { - async function coreCompletion(context: CompletionContext) { + function coreCompletion(context: CompletionContext) { let jsBinding = context.matchBefore(/\$\("[\s\w]*/) let options = baseCompletions || [] @@ -230,7 +232,7 @@ export const jsAutocomplete = ( export const jsHelperAutocomplete = ( baseCompletions: BindingCompletionOption[] ): BindingCompletion => { - async function coreCompletion(context: CompletionContext) { + function coreCompletion(context: CompletionContext) { if (context.matchBefore(/\$\("[\s\w]*/)) { // We are handing a js field completion return null diff --git a/packages/builder/src/types/bindings.ts b/packages/builder/src/types/bindings.ts index ff1b08fb36..5772513d01 100644 --- a/packages/builder/src/types/bindings.ts +++ b/packages/builder/src/types/bindings.ts @@ -1,7 +1,7 @@ import { BindingCompletionOption } from "@budibase/types" import { CompletionContext } from "@codemirror/autocomplete" -export type BindingCompletion = (context: CompletionContext) => Promise<{ +export type BindingCompletion = (context: CompletionContext) => { from: number options: BindingCompletionOption[] -} | null> +} | null diff --git a/packages/types/src/ui/bindings/binding.ts b/packages/types/src/ui/bindings/binding.ts index 17141b5567..1be18b6542 100644 --- a/packages/types/src/ui/bindings/binding.ts +++ b/packages/types/src/ui/bindings/binding.ts @@ -1,9 +1,11 @@ export interface BindingCompletionOption { - section: { + section?: { name: string } label: string + text?: string simple?: boolean + apply?: any // TODO } export interface EnrichedBinding { From aba5d8eee89301422e61cc044e1d2b8692f05bc8 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 13:02:32 +0100 Subject: [PATCH 38/64] Fix types --- .../builder/src/components/common/CodeEditor/CodeEditor.svelte | 2 +- .../builder/src/components/common/bindings/BindingPanel.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index 495862d1b8..7f15775525 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -46,7 +46,7 @@ import { EditorModes } from "./" import { themeStore } from "@/stores/portal" import type { EditorMode } from "@budibase/types" - import { BindingCompletion } from "@/types" + import type { BindingCompletion } from "@/types" export let label: string | undefined = undefined // TODO: work out what best type fits this diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 98b1910e5c..f444e217c7 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -43,7 +43,7 @@ JSONValue, } from "@budibase/types" import type { Log } from "@budibase/string-templates" - import { BindingCompletion } from "@/types" + import type { BindingCompletion } from "@/types" const dispatch = createEventDispatcher() From e961b48c67a451d39d6c274bcc1219eb23557ea6 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 14:29:01 +0100 Subject: [PATCH 39/64] Remove multistep autocomplete --- .../src/components/common/CodeEditor/index.ts | 60 +++++-------------- 1 file changed, 14 insertions(+), 46 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index a1af4710de..3a05c74143 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -7,7 +7,7 @@ import { Helper, Snippet, } from "@budibase/types" -import { CompletionContext, startCompletion } from "@codemirror/autocomplete" +import { CompletionContext } from "@codemirror/autocomplete" import { EditorView } from "@codemirror/view" import { BindingCompletion } from "@/types" @@ -131,8 +131,7 @@ export const snippetAutoComplete = (snippets: Snippet[]): BindingCompletion => { return null } - if (context.matchBefore(/\$\("[\s\w]*/)) { - // We are handing a js field completion + if (wrappedAutocompleteMatch(context)) { return null } @@ -201,11 +200,15 @@ export const hbAutocomplete = ( return coreCompletion } +function wrappedAutocompleteMatch(context: CompletionContext) { + return context.matchBefore(/\$\("[\s\w]*/) +} + export const jsAutocomplete = ( baseCompletions: BindingCompletionOption[] ): BindingCompletion => { function coreCompletion(context: CompletionContext) { - let jsBinding = context.matchBefore(/\$\("[\s\w]*/) + let jsBinding = wrappedAutocompleteMatch(context) let options = baseCompletions || [] if (jsBinding) { @@ -233,61 +236,26 @@ export const jsHelperAutocomplete = ( baseCompletions: BindingCompletionOption[] ): BindingCompletion => { function coreCompletion(context: CompletionContext) { - if (context.matchBefore(/\$\("[\s\w]*/)) { - // We are handing a js field completion + if (wrappedAutocompleteMatch(context)) { return null } - let jsBinding = context.matchBefore(/\bhelpers\.\w*/) + let jsBinding = context.matchBefore(/\b(\w+\.?).*/) + if (!jsBinding || !"helpers.".startsWith(jsBinding.text.split(".")[0])) { + return null + } if (jsBinding) { let options = baseCompletions || [] const match = jsBinding.text.match(/\bhelpers\.(?\w*)/) - if (!match) { - return null - } - const query = match.groups?.["helper"] || "" + const query = match?.groups?.["helper"] || "" let filtered = bindingFilter(options, query) return { from: jsBinding.from, - to: jsBinding.from + match[0].length, + to: jsBinding.from + jsBinding.text.length, filter: false, options: filtered, } - } else { - const prefix = context.matchBefore(/\b\w+/) - if (prefix && "helpers.".startsWith(prefix.text)) { - return { - from: context.pos - prefix.text.length, - to: context.pos, - filter: false, - options: [ - { - label: "helpers.", - type: "text", - simple: true, - apply: ( - view: EditorView, - _completion: BindingCompletionOption, - from: number, - to: number - ) => { - insertBinding( - view, - from, - to, - "helpers.", - EditorModes.JS, - AutocompleteType.TEXT - ) - - // Trigger again the completion, to chain it with the helpers completion - startCompletion(view) - }, - }, - ], - } - } } return null From f146b5dda0713c371a74c71fcfde0dc3ce100b37 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 14:47:48 +0100 Subject: [PATCH 40/64] Update autocomplete package --- packages/builder/package.json | 2 +- yarn.lock | 38 ++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index 0fa4687242..bde21ef447 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -53,7 +53,7 @@ "@budibase/shared-core": "*", "@budibase/string-templates": "*", "@budibase/types": "*", - "@codemirror/autocomplete": "^6.7.1", + "@codemirror/autocomplete": "^6.18.4", "@codemirror/commands": "^6.2.4", "@codemirror/lang-javascript": "^6.1.8", "@codemirror/language": "^6.6.0", diff --git a/yarn.lock b/yarn.lock index b2ca6a0568..e0f30c7a17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2834,7 +2834,7 @@ dependencies: "@bull-board/api" "5.10.2" -"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.7.1": +"@codemirror/autocomplete@^6.0.0": version "6.7.1" resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz#3364799b78dff70fb8f81615536c52ea53ce40b2" integrity sha512-hSxf9S0uB+GV+gBsjY1FZNo53e1FFdzPceRfCfD1gWOnV6o21GfB5J5Wg9G/4h76XZMPrF0A6OCK/Rz5+V1egg== @@ -2844,6 +2844,16 @@ "@codemirror/view" "^6.6.0" "@lezer/common" "^1.0.0" +"@codemirror/autocomplete@^6.18.4": + version "6.18.4" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz#4394f55d6771727179f2e28a871ef46bbbeb11b1" + integrity sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + "@codemirror/commands@^6.2.4": version "6.2.4" resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec" @@ -2893,6 +2903,13 @@ resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2" integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA== +"@codemirror/state@^6.5.0": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" + integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== + dependencies: + "@marijn/find-cluster-break" "^1.0.0" + "@codemirror/theme-one-dark@^6.1.2": version "6.1.2" resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz#fcef9f9cfc17a07836cb7da17c9f6d7231064df8" @@ -2912,6 +2929,15 @@ style-mod "^4.0.0" w3c-keyname "^2.2.4" +"@codemirror/view@^6.17.0": + version "6.36.2" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.2.tgz#aeb644e161440734ac5a153bf6e5b4a4355047be" + integrity sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA== + dependencies: + "@codemirror/state" "^6.5.0" + style-mod "^4.1.0" + w3c-keyname "^2.2.4" + "@colors/colors@1.6.0", "@colors/colors@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" @@ -4133,6 +4159,11 @@ semver "^7.3.5" tar "^6.1.11" +"@marijn/find-cluster-break@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" + integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== + "@mongodb-js/saslprep@^1.1.5": version "1.1.7" resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz#d1700facfd6916c50c2c88fd6d48d363a56c702f" @@ -19961,6 +19992,11 @@ style-mod@^4.0.0: resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad" integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw== +style-mod@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67" + integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw== + stylus-lookup@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" From bf03cd94be7e6de2e0ea239d61ce8edeef069510 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 14:48:49 +0100 Subject: [PATCH 41/64] Move and use existing types --- .../builder/src/components/common/CodeEditor/index.ts | 9 ++------- .../src/components/common/bindings/BindingPanel.svelte | 3 +-- packages/builder/src/types/bindings.ts | 7 ++++--- packages/types/src/ui/bindings/binding.ts | 10 ---------- 4 files changed, 7 insertions(+), 22 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 3a05c74143..3ddae61449 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -1,15 +1,10 @@ import { getManifest } from "@budibase/string-templates" import sanitizeHtml from "sanitize-html" import { groupBy } from "lodash" -import { - BindingCompletionOption, - EditorModesMap, - Helper, - Snippet, -} from "@budibase/types" +import { EditorModesMap, Helper, Snippet } from "@budibase/types" import { CompletionContext } from "@codemirror/autocomplete" import { EditorView } from "@codemirror/view" -import { BindingCompletion } from "@/types" +import { BindingCompletion, BindingCompletionOption } from "@/types" export const EditorModes: EditorModesMap = { JS: { diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index f444e217c7..c0548b6292 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -35,7 +35,6 @@ import { BindingMode, SidePanel } from "@budibase/types" import type { EnrichedBinding, - BindingCompletionOption, Snippet, Helper, CaretPositionFn, @@ -43,7 +42,7 @@ JSONValue, } from "@budibase/types" import type { Log } from "@budibase/string-templates" - import type { BindingCompletion } from "@/types" + import type { BindingCompletion, BindingCompletionOption } from "@/types" const dispatch = createEventDispatcher() diff --git a/packages/builder/src/types/bindings.ts b/packages/builder/src/types/bindings.ts index 5772513d01..00571f1d8b 100644 --- a/packages/builder/src/types/bindings.ts +++ b/packages/builder/src/types/bindings.ts @@ -1,7 +1,8 @@ -import { BindingCompletionOption } from "@budibase/types" -import { CompletionContext } from "@codemirror/autocomplete" +import { CompletionContext, Completion } from "@codemirror/autocomplete" export type BindingCompletion = (context: CompletionContext) => { from: number - options: BindingCompletionOption[] + options: Completion[] } | null + +export type BindingCompletionOption = Completion diff --git a/packages/types/src/ui/bindings/binding.ts b/packages/types/src/ui/bindings/binding.ts index 1be18b6542..fdeb4a6c13 100644 --- a/packages/types/src/ui/bindings/binding.ts +++ b/packages/types/src/ui/bindings/binding.ts @@ -1,13 +1,3 @@ -export interface BindingCompletionOption { - section?: { - name: string - } - label: string - text?: string - simple?: boolean - apply?: any // TODO -} - export interface EnrichedBinding { runtimeBinding: string readableBinding: string From 2271dbfdf3c7626f7c3ed85eea1c6ad651ee4c56 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 15:02:08 +0100 Subject: [PATCH 42/64] Undo yarn.lock changes --- yarn.lock | 69 ++++--------------------------------------------------- 1 file changed, 4 insertions(+), 65 deletions(-) diff --git a/yarn.lock b/yarn.lock index e0f30c7a17..2a1aefad7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2834,7 +2834,7 @@ dependencies: "@bull-board/api" "5.10.2" -"@codemirror/autocomplete@^6.0.0": +"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.7.1": version "6.7.1" resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz#3364799b78dff70fb8f81615536c52ea53ce40b2" integrity sha512-hSxf9S0uB+GV+gBsjY1FZNo53e1FFdzPceRfCfD1gWOnV6o21GfB5J5Wg9G/4h76XZMPrF0A6OCK/Rz5+V1egg== @@ -2844,16 +2844,6 @@ "@codemirror/view" "^6.6.0" "@lezer/common" "^1.0.0" -"@codemirror/autocomplete@^6.18.4": - version "6.18.4" - resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz#4394f55d6771727179f2e28a871ef46bbbeb11b1" - integrity sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA== - dependencies: - "@codemirror/language" "^6.0.0" - "@codemirror/state" "^6.0.0" - "@codemirror/view" "^6.17.0" - "@lezer/common" "^1.0.0" - "@codemirror/commands@^6.2.4": version "6.2.4" resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec" @@ -2903,13 +2893,6 @@ resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2" integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA== -"@codemirror/state@^6.5.0": - version "6.5.2" - resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" - integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== - dependencies: - "@marijn/find-cluster-break" "^1.0.0" - "@codemirror/theme-one-dark@^6.1.2": version "6.1.2" resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz#fcef9f9cfc17a07836cb7da17c9f6d7231064df8" @@ -2929,15 +2912,6 @@ style-mod "^4.0.0" w3c-keyname "^2.2.4" -"@codemirror/view@^6.17.0": - version "6.36.2" - resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.2.tgz#aeb644e161440734ac5a153bf6e5b4a4355047be" - integrity sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA== - dependencies: - "@codemirror/state" "^6.5.0" - style-mod "^4.1.0" - w3c-keyname "^2.2.4" - "@colors/colors@1.6.0", "@colors/colors@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" @@ -4159,11 +4133,6 @@ semver "^7.3.5" tar "^6.1.11" -"@marijn/find-cluster-break@^1.0.0": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" - integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== - "@mongodb-js/saslprep@^1.1.5": version "1.1.7" resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz#d1700facfd6916c50c2c88fd6d48d363a56c702f" @@ -19766,16 +19735,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -19867,7 +19827,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -19881,13 +19841,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -19992,11 +19945,6 @@ style-mod@^4.0.0: resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad" integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw== -style-mod@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67" - integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw== - stylus-lookup@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" @@ -21645,7 +21593,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -21663,15 +21611,6 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 4ee369060efdc39b23dcc37acf6a60e9c19e7c07 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 15:04:42 +0100 Subject: [PATCH 43/64] Update autocomplete --- packages/builder/package.json | 2 +- yarn.lock | 75 +++++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index bde21ef447..a70d19209e 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -53,7 +53,7 @@ "@budibase/shared-core": "*", "@budibase/string-templates": "*", "@budibase/types": "*", - "@codemirror/autocomplete": "^6.18.4", + "@codemirror/autocomplete": "6.9.0", "@codemirror/commands": "^6.2.4", "@codemirror/lang-javascript": "^6.1.8", "@codemirror/language": "^6.6.0", diff --git a/yarn.lock b/yarn.lock index 2a1aefad7a..dffd980299 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2834,16 +2834,26 @@ dependencies: "@bull-board/api" "5.10.2" -"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz#3364799b78dff70fb8f81615536c52ea53ce40b2" - integrity sha512-hSxf9S0uB+GV+gBsjY1FZNo53e1FFdzPceRfCfD1gWOnV6o21GfB5J5Wg9G/4h76XZMPrF0A6OCK/Rz5+V1egg== +"@codemirror/autocomplete@6.9.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.9.0.tgz#1a1e63122288b8f8e1e9d7aff2eb39a83e04d8a9" + integrity sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog== dependencies: "@codemirror/language" "^6.0.0" "@codemirror/state" "^6.0.0" "@codemirror/view" "^6.6.0" "@lezer/common" "^1.0.0" +"@codemirror/autocomplete@^6.0.0": + version "6.18.4" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz#4394f55d6771727179f2e28a871ef46bbbeb11b1" + integrity sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + "@codemirror/commands@^6.2.4": version "6.2.4" resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec" @@ -2893,6 +2903,13 @@ resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2" integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA== +"@codemirror/state@^6.5.0": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" + integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== + dependencies: + "@marijn/find-cluster-break" "^1.0.0" + "@codemirror/theme-one-dark@^6.1.2": version "6.1.2" resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz#fcef9f9cfc17a07836cb7da17c9f6d7231064df8" @@ -2912,6 +2929,15 @@ style-mod "^4.0.0" w3c-keyname "^2.2.4" +"@codemirror/view@^6.17.0": + version "6.36.2" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.2.tgz#aeb644e161440734ac5a153bf6e5b4a4355047be" + integrity sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA== + dependencies: + "@codemirror/state" "^6.5.0" + style-mod "^4.1.0" + w3c-keyname "^2.2.4" + "@colors/colors@1.6.0", "@colors/colors@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" @@ -4133,6 +4159,11 @@ semver "^7.3.5" tar "^6.1.11" +"@marijn/find-cluster-break@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" + integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== + "@mongodb-js/saslprep@^1.1.5": version "1.1.7" resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz#d1700facfd6916c50c2c88fd6d48d363a56c702f" @@ -19735,7 +19766,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -19827,7 +19867,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -19841,6 +19881,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -19945,6 +19992,11 @@ style-mod@^4.0.0: resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad" integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw== +style-mod@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67" + integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw== + stylus-lookup@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" @@ -21593,7 +21645,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -21611,6 +21663,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 11dd47a9d22331173540b8961acdb51d40c67ba5 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 15:37:16 +0100 Subject: [PATCH 44/64] Use display lables and default tools for helpers --- .../src/components/common/CodeEditor/index.ts | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 3ddae61449..6cb0dfe582 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -155,7 +155,7 @@ export const snippetAutoComplete = (snippets: Snippet[]): BindingCompletion => { const bindingFilter = (options: BindingCompletionOption[], query: string) => { return options.filter(completion => { - const section_parsed = completion.section?.name.toLowerCase() + const section_parsed = completion.section?.toString().toLowerCase() const label_parsed = completion.label.toLowerCase() const query_parsed = query.toLowerCase() @@ -235,25 +235,18 @@ export const jsHelperAutocomplete = ( return null } - let jsBinding = context.matchBefore(/\b(\w+\.?).*/) - if (!jsBinding || !"helpers.".startsWith(jsBinding.text.split(".")[0])) { + const word = context.matchBefore(/\b\w*/) + if (!word || (word.from == word.to && !context.explicit)) { return null } - - if (jsBinding) { - let options = baseCompletions || [] - const match = jsBinding.text.match(/\bhelpers\.(?\w*)/) - const query = match?.groups?.["helper"] || "" - let filtered = bindingFilter(options, query) - return { - from: jsBinding.from, - to: jsBinding.from + jsBinding.text.length, - filter: false, - options: filtered, - } + return { + from: word.from, + options: baseCompletions.map(helper => ({ + section: helper.section, + displayLabel: helper.label, + label: `helpers.${helper.label}()`, + })), } - - return null } return coreCompletion From 5d12cc3b7e3e61f7eb1229ef7dc37fad72fbd591 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 15:46:09 +0100 Subject: [PATCH 45/64] Format snippers --- .../src/components/common/CodeEditor/index.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 6cb0dfe582..12b5f8498d 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -137,17 +137,9 @@ export const snippetAutoComplete = (snippets: Snippet[]): BindingCompletion => { return { from: word.from, options: snippets.map(snippet => ({ + section: buildSectionHeader("snippets", "Snippets", "Code", 100), label: `snippets.${snippet.name}`, - type: "text", - simple: true, - apply: ( - view: EditorView, - completion: BindingCompletionOption, - from: number, - to: number - ) => { - insertSnippet(view, from, to, completion.label) - }, + displayLabel: snippet.name, })), } } @@ -239,6 +231,7 @@ export const jsHelperAutocomplete = ( if (!word || (word.from == word.to && !context.explicit)) { return null } + return { from: word.from, options: baseCompletions.map(helper => ({ From cb41ee81c6af8d3f3a19667cd0da0df556e7a7d6 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 15:47:16 +0100 Subject: [PATCH 46/64] Remove unnecessary code --- .../src/components/common/CodeEditor/index.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 12b5f8498d..138477e197 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -357,25 +357,6 @@ export const insertBinding = ( }) } -export const insertSnippet = ( - view: EditorView, - from: number, - to: number, - text: string -) => { - let cursorPos = from + text.length - view.dispatch({ - changes: { - from, - to, - insert: text, - }, - selection: { - anchor: cursorPos, - }, - }) -} - // TODO: typing in this function isn't great export const bindingsToCompletions = ( bindings: any, From af6c4b4b8c338860c1ab33bf045be764d97b4c46 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 15:50:32 +0100 Subject: [PATCH 47/64] Clean code --- .../src/components/common/CodeEditor/index.ts | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 138477e197..c6f65c2f5e 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -22,15 +22,7 @@ export const EditorModes: EditorModesMap = { }, } -export const SECTIONS = { - HB_HELPER: { - name: "Helper", - type: "helper", - icon: "Code", - }, -} - -export const buildHelperInfoNode = (completion: any, helper: Helper) => { +const buildHelperInfoNode = (completion: any, helper: Helper) => { const ele = document.createElement("div") ele.classList.add("info-bubble") @@ -62,7 +54,7 @@ const toSpectrumIcon = (name: string) => { ` } -export const buildSectionHeader = ( +const buildSectionHeader = ( type: string, sectionName: string, icon: string, @@ -81,12 +73,11 @@ export const buildSectionHeader = ( } } -export const helpersToCompletion = ( +const helpersToCompletion = ( helpers: Record, mode: { name: "javascript" | "handlebars" } ): BindingCompletionOption[] => { - const { type, name: sectionName, icon } = SECTIONS.HB_HELPER - const helperSection = buildSectionHeader(type, sectionName, icon, 99) + const helperSection = buildSectionHeader("helper", "Helper", "Code", 99) return Object.keys(helpers).flatMap(helperName => { const helper = helpers[helperName] @@ -245,7 +236,7 @@ export const jsHelperAutocomplete = ( return coreCompletion } -export const buildBindingInfoNode = ( +const buildBindingInfoNode = ( _completion: BindingCompletionOption, binding: any ) => { @@ -313,7 +304,7 @@ const enum AutocompleteType { } // Autocomplete apply behaviour -export const insertBinding = ( +const insertBinding = ( view: EditorView, from: number, to: number, From e56431766bd6f53aedc1f741856eeca0f5b22f61 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 16:06:41 +0100 Subject: [PATCH 48/64] Clean code --- .../src/components/common/CodeEditor/index.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index c6f65c2f5e..c9a91c5a28 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -22,7 +22,7 @@ export const EditorModes: EditorModesMap = { }, } -const buildHelperInfoNode = (completion: any, helper: Helper) => { +const buildHelperInfoNode = (helper: Helper) => { const ele = document.createElement("div") ele.classList.add("info-bubble") @@ -83,9 +83,7 @@ const helpersToCompletion = ( const helper = helpers[helperName] return { label: helperName, - info: (completion: BindingCompletionOption) => { - return buildHelperInfoNode(completion, helper) - }, + info: () => buildHelperInfoNode(helper), type: "helper", section: helperSection, detail: "Function", @@ -236,10 +234,10 @@ export const jsHelperAutocomplete = ( return coreCompletion } -const buildBindingInfoNode = ( - _completion: BindingCompletionOption, - binding: any -) => { +const buildBindingInfoNode = (binding: { + valueHTML: string + value: string | null +}) => { if (!binding.valueHTML || binding.value == null) { return null } @@ -385,9 +383,7 @@ export const bindingsToCompletions = ( acc.push({ label: binding.display?.name || binding.readableBinding || "NO NAME", - info: (completion: BindingCompletionOption) => { - return buildBindingInfoNode(completion, binding) - }, + info: () => buildBindingInfoNode(binding), type: "binding", detail: displayType, section: bindingSectionHeader, From e07cb6fb6893d2762ac5667212a5378026c855a4 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 16:11:32 +0100 Subject: [PATCH 49/64] Type anys --- .../src/components/common/CodeEditor/index.ts | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index c9a91c5a28..cad75cd6bb 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -350,7 +350,7 @@ const insertBinding = ( export const bindingsToCompletions = ( bindings: any, mode: { name: "javascript" | "handlebars" } -) => { +): BindingCompletionOption[] => { const bindingByCategory = groupBy(bindings, "category") const categoryMeta = bindings?.reduce((acc: any, ele: any) => { acc[ele.category] = acc[ele.category] || {} @@ -364,21 +364,22 @@ export const bindingsToCompletions = ( return acc }, {}) - const completions = Object.keys(bindingByCategory).reduce( - (comps: any, catKey: string) => { - const { icon, rank } = categoryMeta[catKey] || {} + const completions = Object.keys(bindingByCategory).reduce< + BindingCompletionOption[] + >((comps, catKey) => { + const { icon, rank } = categoryMeta[catKey] || {} - const bindingSectionHeader = buildSectionHeader( - // @ts-ignore something wrong with this - logically this should be dictionary - bindingByCategory.type, - catKey, - icon || "", - typeof rank == "number" ? rank : 1 - ) + const bindingSectionHeader = buildSectionHeader( + // @ts-ignore something wrong with this - logically this should be dictionary + bindingByCategory.type, + catKey, + icon || "", + typeof rank == "number" ? rank : 1 + ) - return [ - ...comps, - ...bindingByCategory[catKey].reduce((acc, binding) => { + comps.push( + ...bindingByCategory[catKey].reduce( + (acc, binding) => { let displayType = binding.fieldSchema?.type || binding.display?.type acc.push({ label: @@ -404,11 +405,13 @@ export const bindingsToCompletions = ( }, }) return acc - }, []), - ] - }, - [] - ) + }, + [] + ) + ) + + return comps + }, []) return completions } From cc0233eb043c27cad489ecffc6d1931a22ec9fff Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 16:54:45 +0100 Subject: [PATCH 50/64] Fix when typing `.` on helpers. or snippets. --- .../src/components/common/CodeEditor/index.ts | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index cad75cd6bb..6e2f68a7b6 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -110,28 +110,13 @@ export const getHelperCompletions = (mode: { } export const snippetAutoComplete = (snippets: Snippet[]): BindingCompletion => { - return function myCompletions(context: CompletionContext) { - if (!snippets?.length) { - return null - } - - if (wrappedAutocompleteMatch(context)) { - return null - } - - const word = context.matchBefore(/\b\w*/) - if (!word || (word.from == word.to && !context.explicit)) { - return null - } - return { - from: word.from, - options: snippets.map(snippet => ({ - section: buildSectionHeader("snippets", "Snippets", "Code", 100), - label: `snippets.${snippet.name}`, - displayLabel: snippet.name, - })), - } - } + return setAutocomplete( + snippets.map(snippet => ({ + section: buildSectionHeader("snippets", "Snippets", "Code", 100), + label: `snippets.${snippet.name}`, + displayLabel: snippet.name, + })) + ) } const bindingFilter = (options: BindingCompletionOption[], query: string) => { @@ -211,27 +196,33 @@ export const jsAutocomplete = ( export const jsHelperAutocomplete = ( baseCompletions: BindingCompletionOption[] ): BindingCompletion => { - function coreCompletion(context: CompletionContext) { + return setAutocomplete( + baseCompletions.map(helper => ({ + section: helper.section, + displayLabel: helper.label, + label: `helpers.${helper.label}()`, + })) + ) +} + +function setAutocomplete( + options: BindingCompletionOption[] +): BindingCompletion { + return function (context: CompletionContext) { if (wrappedAutocompleteMatch(context)) { return null } - const word = context.matchBefore(/\b\w*/) + const word = context.matchBefore(/\b\w*(\.\w*)?/) if (!word || (word.from == word.to && !context.explicit)) { return null } return { from: word.from, - options: baseCompletions.map(helper => ({ - section: helper.section, - displayLabel: helper.label, - label: `helpers.${helper.label}()`, - })), + options, } } - - return coreCompletion } const buildBindingInfoNode = (binding: { From affaf45d4ff5013ebfb540849bd66bd650d65912 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 17:02:04 +0100 Subject: [PATCH 51/64] Update --- packages/builder/src/components/common/CodeEditor/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 6e2f68a7b6..5fa7224d11 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -77,7 +77,7 @@ const helpersToCompletion = ( helpers: Record, mode: { name: "javascript" | "handlebars" } ): BindingCompletionOption[] => { - const helperSection = buildSectionHeader("helper", "Helper", "Code", 99) + const helperSection = buildSectionHeader("helper", "Helpers", "Code", 99) return Object.keys(helpers).flatMap(helperName => { const helper = helpers[helperName] From 7c91ce89587f3a9c71a1b7a30c26ca918b49c267 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 11 Feb 2025 17:03:26 +0100 Subject: [PATCH 52/64] Lint --- .../builder/src/components/common/CodeEditor/CodeEditor.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index 7f15775525..2acde47539 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -10,7 +10,6 @@ closeBracketsKeymap, acceptCompletion, completionStatus, - CompletionContext, } from "@codemirror/autocomplete" import { lineNumbers, From 6cc8fb0cc30af01fd484d0278e3f25da1a42845e Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 12 Feb 2025 16:17:37 +0100 Subject: [PATCH 53/64] Add extra info back --- packages/builder/src/components/common/CodeEditor/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/CodeEditor/index.ts b/packages/builder/src/components/common/CodeEditor/index.ts index 5fa7224d11..5529484665 100644 --- a/packages/builder/src/components/common/CodeEditor/index.ts +++ b/packages/builder/src/components/common/CodeEditor/index.ts @@ -198,7 +198,7 @@ export const jsHelperAutocomplete = ( ): BindingCompletion => { return setAutocomplete( baseCompletions.map(helper => ({ - section: helper.section, + ...helper, displayLabel: helper.label, label: `helpers.${helper.label}()`, })) From ec5111f790730f358851cab44628eb491c786624 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 12 Feb 2025 16:21:33 +0100 Subject: [PATCH 54/64] Remove non-needed target --- packages/builder/tsconfig.build.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/builder/tsconfig.build.json b/packages/builder/tsconfig.build.json index 77606ef8ed..119fe56c81 100644 --- a/packages/builder/tsconfig.build.json +++ b/packages/builder/tsconfig.build.json @@ -1,7 +1,6 @@ { "extends": "../../tsconfig.build.json", "compilerOptions": { - "target": "es2018", "allowJs": true }, "include": ["./src/**/*"], From 66491fe3ca680a3db93b8761930ca1a3e8689c9a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 12 Feb 2025 16:44:11 +0100 Subject: [PATCH 55/64] Add default dev OPENAI_API_KEY --- packages/server/scripts/dev/manage.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/server/scripts/dev/manage.js b/packages/server/scripts/dev/manage.js index 84e1abea69..a07fa1b582 100644 --- a/packages/server/scripts/dev/manage.js +++ b/packages/server/scripts/dev/manage.js @@ -46,6 +46,7 @@ async function init() { HTTP_LOGGING: "0", VERSION: "0.0.0+local", PASSWORD_MIN_LENGTH: "1", + OPENAI_API_KEY: "sk-abcdefghijklmnopqrstuvwxyz1234567890abcd", } config = { ...config, ...existingConfig } From e8ad7280a9f69a2c37443b55223142e7f754e5ed Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 12 Feb 2025 16:58:24 +0000 Subject: [PATCH 56/64] Reverting svelte config update for SSR typescript - this doesn't seem to work well at all, rather than updating this to Typescript for one type definition I have added it via a type comment instead. --- packages/server/jest.config.ts | 15 +-------------- packages/server/package.json | 2 -- packages/server/scripts/svelteTransformer.js | 11 +++++++++++ .../static/templates/BudibaseApp.svelte | 7 ++++--- packages/server/svelte.config.js | 5 ----- yarn.lock | 5 ----- 6 files changed, 16 insertions(+), 29 deletions(-) create mode 100644 packages/server/scripts/svelteTransformer.js delete mode 100644 packages/server/svelte.config.js diff --git a/packages/server/jest.config.ts b/packages/server/jest.config.ts index 6fadec6e29..6341c8e5bd 100644 --- a/packages/server/jest.config.ts +++ b/packages/server/jest.config.ts @@ -21,20 +21,7 @@ const baseConfig: Config.InitialProjectOptions = { transform: { "^.+\\.ts?$": "@swc/jest", "^.+\\.js?$": "@swc/jest", - "^.+\\.svelte$": [ - "jest-chain-transform", // https://github.com/svelteness/svelte-jester/issues/166 - { - transformers: [ - [ - "svelte-jester", - { - preprocess: true, - }, - ], - "@swc/jest", - ], - }, - ], + "^.+\\.svelte?$": "/scripts/svelteTransformer.js", }, transformIgnorePatterns: ["/node_modules/(?!svelte/).*"], moduleNameMapper: { diff --git a/packages/server/package.json b/packages/server/package.json index b73d3f5f99..fd448629e8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -139,7 +139,6 @@ "@babel/core": "^7.22.5", "@babel/preset-env": "7.16.11", "@jest/types": "^29.6.3", - "@sveltejs/vite-plugin-svelte": "1.4.0", "@swc/core": "1.3.71", "@swc/jest": "0.2.27", "@types/archiver": "6.0.2", @@ -165,7 +164,6 @@ "docker-compose": "0.23.17", "ioredis-mock": "8.9.0", "jest": "29.7.0", - "jest-chain-transform": "^0.0.8", "jest-extended": "^4.0.2", "jest-openapi": "0.14.2", "nock": "13.5.4", diff --git a/packages/server/scripts/svelteTransformer.js b/packages/server/scripts/svelteTransformer.js new file mode 100644 index 0000000000..ecc8bbbe5d --- /dev/null +++ b/packages/server/scripts/svelteTransformer.js @@ -0,0 +1,11 @@ +const { compile } = require("svelte/compiler") +const { transformSync } = require("@babel/core") + +module.exports = { + process(sourceText) { + const { js } = compile(sourceText, { css: "injected", generate: "ssr" }) + const { code } = transformSync(js.code, { babelrc: true }) + + return { code: code } + }, +} \ No newline at end of file diff --git a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte index ccaaf22ad1..809f893169 100644 --- a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte +++ b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte @@ -1,8 +1,9 @@ - diff --git a/packages/server/svelte.config.js b/packages/server/svelte.config.js deleted file mode 100644 index 77aeada229..0000000000 --- a/packages/server/svelte.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const { vitePreprocess } = require("@sveltejs/vite-plugin-svelte") - -module.exports = { - preprocess: vitePreprocess(), -} diff --git a/yarn.lock b/yarn.lock index b2ca6a0568..7fb2e6175f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13739,11 +13739,6 @@ jake@^10.8.5: filelist "^1.0.1" minimatch "^3.0.4" -jest-chain-transform@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/jest-chain-transform/-/jest-chain-transform-0.0.8.tgz#cbb4d3aef8d02678b1852968a9b0c861f75eef5a" - integrity sha512-AELTTzYJ34WrmQKAbxUGT+xqnAHu0/XJZhahYNGvBVUhnAayjm1QmT45DQjwEbQPQp7gn6CXzu6rZA03riwBuw== - jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" From 6ccd8d66d508a20bed939b8ed56ef230eade83d1 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 12 Feb 2025 17:06:01 +0000 Subject: [PATCH 57/64] Linting. --- packages/server/scripts/svelteTransformer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/scripts/svelteTransformer.js b/packages/server/scripts/svelteTransformer.js index ecc8bbbe5d..6b67971581 100644 --- a/packages/server/scripts/svelteTransformer.js +++ b/packages/server/scripts/svelteTransformer.js @@ -8,4 +8,4 @@ module.exports = { return { code: code } }, -} \ No newline at end of file +} From f70b5cb1293ecf6b835a1a36a28d2df76b4a4d21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 19:53:48 +0000 Subject: [PATCH 58/64] Bump koa from 2.13.4 to 2.15.4 Bumps [koa](https://github.com/koajs/koa) from 2.13.4 to 2.15.4. - [Release notes](https://github.com/koajs/koa/releases) - [Changelog](https://github.com/koajs/koa/blob/2.15.4/History.md) - [Commits](https://github.com/koajs/koa/compare/2.13.4...2.15.4) --- updated-dependencies: - dependency-name: koa dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- packages/server/package.json | 2 +- packages/worker/package.json | 2 +- yarn.lock | 74 ++++++++++++------------------------ 3 files changed, 26 insertions(+), 52 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index fd448629e8..9a70ecba9c 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -99,7 +99,7 @@ "jsonschema": "1.4.0", "jsonwebtoken": "9.0.2", "knex": "2.4.2", - "koa": "2.13.4", + "koa": "2.15.4", "koa-body": "4.2.0", "koa-compress": "4.0.1", "koa-send": "5.0.1", diff --git a/packages/worker/package.json b/packages/worker/package.json index ff21d88ac0..c5e32d11a0 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -58,7 +58,7 @@ "joi": "17.6.0", "jsonwebtoken": "9.0.2", "knex": "2.4.2", - "koa": "2.13.4", + "koa": "2.15.4", "koa-body": "4.2.0", "koa-compress": "4.0.1", "koa-passport": "4.1.4", diff --git a/yarn.lock b/yarn.lock index 3191513b07..23bb5fe1d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2777,7 +2777,7 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": +"@budibase/pro@*", "@budibase/pro@npm:@budibase/pro@latest": version "3.4.6" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.4.6.tgz#62b6ee13a015b98d4768dc7821f468f8177da3e9" integrity sha512-MC3P5SMokmqbjejZMlNM6z7NB9o5H6hZ++yVvbyThniBPYfuDc2ssa1HNwwcuNE3uRLhcxcKe8CY/0SbFgn51g== @@ -9390,7 +9390,7 @@ cookiejar@^2.1.4: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== -cookies@0.8.0, cookies@~0.8.0: +cookies@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== @@ -9398,6 +9398,14 @@ cookies@0.8.0, cookies@~0.8.0: depd "~2.0.0" keygrip "~1.1.0" +cookies@~0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.9.1.tgz#3ffed6f60bb4fb5f146feeedba50acc418af67e3" + integrity sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw== + dependencies: + depd "~2.0.0" + keygrip "~1.1.0" + copyfiles@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5" @@ -9789,10 +9797,10 @@ dd-trace@5.26.0: shell-quote "^1.8.1" tlhunter-sorted-set "^0.1.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: - version "4.3.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" - integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== dependencies: ms "^2.1.3" @@ -9810,10 +9818,10 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.3.5: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== +debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: ms "^2.1.3" @@ -14701,45 +14709,16 @@ koa2-ratelimit@1.1.1: resolved "https://registry.yarnpkg.com/koa2-ratelimit/-/koa2-ratelimit-1.1.1.tgz#9c1d8257770e4a0a08063ba2ddcaf690fd457d23" integrity sha512-IpxGMdZqEhMykW0yYKGVB4vDEacPvSBH4hNpDL38ABj3W2KHNLujAljGEDg7eEjXvrRbXRSWXzANhV3c9v7nyg== -koa@2.13.4: - version "2.13.4" - resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e" - integrity sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g== +koa@2.15.4, koa@^2.13.1, koa@^2.13.4: + version "2.15.4" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.15.4.tgz#7000b3d8354558671adb1ba1b1c09bedb5f8da75" + integrity sha512-7fNBIdrU2PEgLljXoPWoyY4r1e+ToWCmzS/wwMPbUNs7X+5MMET1ObhJBlUkF5uZG9B6QhM2zS1TsH6adegkiQ== dependencies: accepts "^1.3.5" cache-content-type "^1.0.0" content-disposition "~0.5.2" content-type "^1.0.4" - cookies "~0.8.0" - debug "^4.3.2" - delegates "^1.0.0" - depd "^2.0.0" - destroy "^1.0.4" - encodeurl "^1.0.2" - escape-html "^1.0.3" - fresh "~0.5.2" - http-assert "^1.3.0" - http-errors "^1.6.3" - is-generator-function "^1.0.7" - koa-compose "^4.1.0" - koa-convert "^2.0.0" - on-finished "^2.3.0" - only "~0.0.2" - parseurl "^1.3.2" - statuses "^1.5.0" - type-is "^1.6.16" - vary "^1.1.2" - -koa@^2.13.1, koa@^2.13.4: - version "2.14.1" - resolved "https://registry.yarnpkg.com/koa/-/koa-2.14.1.tgz#defb9589297d8eb1859936e777f3feecfc26925c" - integrity sha512-USJFyZgi2l0wDgqkfD27gL4YGno7TfUkcmOe6UOLFOVuN+J7FwnNu4Dydl4CUQzraM1lBAiGed0M9OVJoT0Kqw== - dependencies: - accepts "^1.3.5" - cache-content-type "^1.0.0" - content-disposition "~0.5.2" - content-type "^1.0.4" - cookies "~0.8.0" + cookies "~0.9.0" debug "^4.3.2" delegates "^1.0.0" depd "^2.0.0" @@ -20451,11 +20430,6 @@ timekeeper@2.2.0: resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.2.0.tgz#9645731fce9e3280a18614a57a9d1b72af3ca368" integrity sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A== -timekeeper@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.3.1.tgz#2deb6e0b95d93625fda84c18d47f84a99e4eba01" - integrity sha512-LeQRS7/4JcC0PgdSFnfUiStQEdiuySlCj/5SJ18D+T1n9BoY7PxKFfCwLulpHXoLUFr67HxBddQdEX47lDGx1g== - tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -20683,7 +20657,7 @@ tsconfig-paths@^3.10.1, tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: +tsconfig-paths@^4.1.2: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== From 4685a4591646c10bc624818bbfddd941f276988c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 13 Feb 2025 09:06:44 +0000 Subject: [PATCH 59/64] Add default icon for icon settings --- packages/builder/src/stores/builder/components.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index d1acb4cfbd..440d0c1993 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -299,6 +299,8 @@ export class ComponentStore extends BudiStore { component[setting.key] = fieldOptions[0] component.label = fieldOptions[0] } + } else if (setting.type === "icon") { + component[setting.key] = "ri-star-fill" } else if (useDefaultValues && setting.defaultValue !== undefined) { // Use default value where required component[setting.key] = setting.defaultValue From b6185c3925a155901c07a37607674cd375454d30 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 13 Feb 2025 09:18:18 +0000 Subject: [PATCH 60/64] Attempt to auto-fill data provider type settings when adding components --- .../builder/src/stores/builder/components.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index 440d0c1993..b3e897fa3c 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -11,6 +11,7 @@ import { findComponentParent, findAllMatchingComponents, makeComponentUnique, + findComponentType, } from "@/helpers/components" import { getComponentFieldOptions } from "@/helpers/formFields" import { selectedScreen } from "./screens" @@ -263,14 +264,25 @@ export class ComponentStore extends BudiStore { type: "table", } } else if (setting.type === "dataProvider") { - // Pick closest data provider where required + let providerId + + // Pick closest parent data provider if one exists const path = findComponentPath(screen.props, treeId) const providers = path.filter((component: Component) => component._component?.endsWith("/dataprovider") ) - if (providers.length) { - const id = providers[providers.length - 1]?._id - component[setting.key] = `{{ literal ${safe(id)} }}` + providerId = providers[providers.length - 1]?._id + + // If none in our direct path, select the first one the screen + if (!providerId) { + providerId = findComponentType( + screen.props, + "@budibase/standard-components/dataprovider" + )?._id + } + + if (providerId) { + component[setting.key] = `{{ literal ${safe(providerId)} }}` } } else if (setting.type.startsWith("field/")) { // Autofill form field names From 304e66735b2cbe7b9b1b05a8ad643699dce1b173 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 13 Feb 2025 11:54:56 +0100 Subject: [PATCH 61/64] Don't allow helpers on snippets --- .../common/bindings/BindingPanel.svelte | 18 ++++++++++++++---- .../common/bindings/SnippetDrawer.svelte | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index c0548b6292..3edcd34317 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -91,7 +91,10 @@ $: bindingCompletions = bindingsToCompletions(enrichedBindings, editorMode) $: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos) $: hbsCompletions = getHBSCompletions(bindingCompletions) - $: jsCompletions = getJSCompletions(bindingCompletions, snippets, useSnippets) + $: jsCompletions = getJSCompletions(bindingCompletions, snippets, { + useHelpers: allowHelpers, + useSnippets, + }) $: { // Ensure a valid side panel option is always selected if (sidePanel && !sidePanelOptions.includes(sidePanel)) { @@ -111,13 +114,20 @@ const getJSCompletions = ( bindingCompletions: BindingCompletionOption[], snippets: Snippet[] | null, - useSnippets?: boolean + config: { + useHelpers: boolean + useSnippets: boolean + } ) => { const completions: BindingCompletion[] = [ jsAutocomplete([...bindingCompletions]), - jsHelperAutocomplete([...getHelperCompletions(EditorModes.JS)]), ] - if (useSnippets && snippets) { + if (config.useHelpers) { + completions.push( + jsHelperAutocomplete([...getHelperCompletions(EditorModes.JS)]) + ) + } + if (config.useSnippets && snippets) { completions.push(snippetAutoComplete(snippets)) } return completions diff --git a/packages/builder/src/components/common/bindings/SnippetDrawer.svelte b/packages/builder/src/components/common/bindings/SnippetDrawer.svelte index f10c44f81f..4862217b13 100644 --- a/packages/builder/src/components/common/bindings/SnippetDrawer.svelte +++ b/packages/builder/src/components/common/bindings/SnippetDrawer.svelte @@ -118,6 +118,7 @@ allowHBS={false} allowJS allowSnippets={false} + allowHelpers={false} showTabBar={false} placeholder="return function(input) ❴ ... ❵" value={code} From 1d81949a982a727e286ef53dca7251e3808052d1 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 13 Feb 2025 12:03:54 +0100 Subject: [PATCH 62/64] Don't autocomplete $("") if there is nothing to autocomplete --- .../src/components/common/bindings/BindingPanel.svelte | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 3edcd34317..4bd37bf72c 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -119,9 +119,10 @@ useSnippets: boolean } ) => { - const completions: BindingCompletion[] = [ - jsAutocomplete([...bindingCompletions]), - ] + const completions: BindingCompletion[] = [] + if (bindingCompletions.length) { + completions.push(jsAutocomplete([...bindingCompletions])) + } if (config.useHelpers) { completions.push( jsHelperAutocomplete([...getHelperCompletions(EditorModes.JS)]) @@ -389,7 +390,7 @@ autofocus={autofocusEditor} placeholder={placeholder || "Add bindings by typing $ or use the menu on the right"} - jsBindingWrapping + jsBindingWrapping={bindingCompletions.length > 0} /> {/key} {/if} From 82dc024623158431d5ed7b5bd0cd52c7f01819f2 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Thu, 13 Feb 2025 12:21:56 +0000 Subject: [PATCH 63/64] Bump version to 3.4.7 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index c893e4b402..18c131fe56 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.4.6", + "version": "3.4.7", "npmClient": "yarn", "concurrency": 20, "command": { From c7da9e6b96dd539f253bc488395c57508c90dbd8 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 13 Feb 2025 12:33:13 +0000 Subject: [PATCH 64/64] Updating yarn lock. --- yarn.lock | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 99275e7027..efbac62306 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2777,7 +2777,7 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@*", "@budibase/pro@npm:@budibase/pro@latest": +"@budibase/pro@npm:@budibase/pro@latest": version "3.4.6" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.4.6.tgz#62b6ee13a015b98d4768dc7821f468f8177da3e9" integrity sha512-MC3P5SMokmqbjejZMlNM6z7NB9o5H6hZ++yVvbyThniBPYfuDc2ssa1HNwwcuNE3uRLhcxcKe8CY/0SbFgn51g== @@ -20466,6 +20466,11 @@ timekeeper@2.2.0: resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.2.0.tgz#9645731fce9e3280a18614a57a9d1b72af3ca368" integrity sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A== +timekeeper@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.3.1.tgz#2deb6e0b95d93625fda84c18d47f84a99e4eba01" + integrity sha512-LeQRS7/4JcC0PgdSFnfUiStQEdiuySlCj/5SJ18D+T1n9BoY7PxKFfCwLulpHXoLUFr67HxBddQdEX47lDGx1g== + tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -20693,7 +20698,7 @@ tsconfig-paths@^3.10.1, tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tsconfig-paths@^4.1.2: +tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==