Merge branch 'master' into execute-script-v2

This commit is contained in:
deanhannigan 2025-03-03 12:39:52 +00:00 committed by GitHub
commit f37ffb0930
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 104 additions and 62 deletions

View File

@ -94,6 +94,15 @@ export default [
allowImportExportEverywhere: true,
},
},
plugins: {
...config.plugins,
"@typescript-eslint": tseslint.plugin,
},
rules: {
...config.rules,
"@typescript-eslint/consistent-type-imports": "error",
},
})),
...tseslint.configs.strict.map(config => ({
...config,

View File

@ -27,7 +27,7 @@ export type UpdateHandler = (
interface Opts {
anchor?: HTMLElement
align: PopoverAlignment
align: PopoverAlignment | `${PopoverAlignment}`
maxHeight?: number
maxWidth?: number
minWidth?: number

View File

@ -19,7 +19,8 @@
import { PopoverAlignment } from "../constants"
export let anchor: HTMLElement
export let align: PopoverAlignment = PopoverAlignment.Right
export let align: PopoverAlignment | `${PopoverAlignment}` =
PopoverAlignment.Right
export let portalTarget: string | undefined = undefined
export let minWidth: number | undefined = undefined
export let maxWidth: number | undefined = undefined

View File

@ -422,7 +422,7 @@
{context}
addHelper={onSelectHelper}
addBinding={onSelectBinding}
mode={editorMode}
{mode}
/>
{:else if sidePanel === SidePanel.Evaluation}
<EvaluationSidePanel

View File

@ -1,32 +1,41 @@
<script>
<script lang="ts">
import groupBy from "lodash/fp/groupBy"
import { convertToJS } from "@budibase/string-templates"
import { Input, Layout, Icon, Popover } from "@budibase/bbui"
import { handlebarsCompletions } from "@/constants/completions"
import type { EnrichedBinding, Helper } from "@budibase/types"
import { BindingMode } from "@budibase/types"
export let addHelper
export let addBinding
export let bindings
export let mode
export let allowHelpers
export let addHelper: (_helper: Helper, _js?: boolean) => void
export let addBinding: (_binding: EnrichedBinding) => void
export let bindings: EnrichedBinding[]
export let mode: BindingMode
export let allowHelpers: boolean
export let context = null
let search = ""
let searching = false
let popover
let popoverAnchor
let hoverTarget
let popover: Popover
let popoverAnchor: HTMLElement | null
let hoverTarget: {
helper: boolean
code: string
description?: string
} | null
let helpers = handlebarsCompletions()
let selectedCategory
let hideTimeout
let selectedCategory: string | null
let hideTimeout: ReturnType<typeof setTimeout> | null
$: bindingIcons = bindings?.reduce((acc, ele) => {
$: bindingIcons = bindings?.reduce<Record<string, string>>((acc, ele) => {
if (ele.icon) {
acc[ele.category] = acc[ele.category] || ele.icon
}
return acc
}, {})
$: categoryIcons = { ...bindingIcons, Helpers: "MagicWand" }
$: categoryIcons = {
...bindingIcons,
Helpers: "MagicWand",
} as Record<string, string>
$: categories = Object.entries(groupBy("category", bindings))
$: categoryNames = getCategoryNames(categories)
$: searchRgx = new RegExp(search, "ig")
@ -48,11 +57,11 @@
(!search ||
helper.label.match(searchRgx) ||
helper.description.match(searchRgx)) &&
(mode.name !== "javascript" || helper.allowsJs)
(mode !== BindingMode.JavaScript || helper.allowsJs)
)
})
const getHelperExample = (helper, js) => {
const getHelperExample = (helper: Helper, js: boolean) => {
let example = helper.example || ""
if (js) {
example = convertToJS(example).split("\n")[0].split("= ")[1]
@ -63,15 +72,18 @@
return example || ""
}
const getCategoryNames = categories => {
let names = [...categories.map(cat => cat[0])]
const getCategoryNames = (categories: [string, EnrichedBinding[]][]) => {
const names = [...categories.map(cat => cat[0])]
if (allowHelpers) {
names.push("Helpers")
}
return names
}
const showBindingPopover = (binding, target) => {
const showBindingPopover = (
binding: EnrichedBinding,
target: HTMLElement
) => {
if (!context || !binding.value || binding.value === "") {
return
}
@ -84,7 +96,7 @@
popover.show()
}
const showHelperPopover = (helper, target) => {
const showHelperPopover = (helper: any, target: HTMLElement) => {
stopHidingPopover()
if (!helper.displayText && helper.description) {
return
@ -93,7 +105,7 @@
hoverTarget = {
helper: true,
description: helper.description,
code: getHelperExample(helper, mode.name === "javascript"),
code: getHelperExample(helper, mode === BindingMode.JavaScript),
}
popover.show()
}
@ -119,13 +131,14 @@
search = ""
}
const stopSearching = e => {
const stopSearching = (e: Event) => {
e.stopPropagation()
searching = false
search = ""
}
</script>
{#if popoverAnchor && hoverTarget}
<Popover
align="left-outside"
bind:this={popover}
@ -150,6 +163,7 @@
{/if}
</div>
</Popover>
{/if}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
@ -173,7 +187,7 @@
<div class="search-input">
<Input
placeholder="Search for bindings"
autocomplete="off"
autocomplete={false}
bind:value={search}
autofocus
/>
@ -230,7 +244,8 @@
{#each category.bindings as binding}
<li
class="binding"
on:mouseenter={e => showBindingPopover(binding, e.target)}
on:mouseenter={e =>
showBindingPopover(binding, e.currentTarget)}
on:mouseleave={hidePopover}
on:click={() => addBinding(binding)}
>
@ -264,9 +279,11 @@
{#each filteredHelpers as helper}
<li
class="binding"
on:mouseenter={e => showHelperPopover(helper, e.target)}
on:mouseenter={e =>
showHelperPopover(helper, e.currentTarget)}
on:mouseleave={hidePopover}
on:click={() => addHelper(helper, mode.name === "javascript")}
on:click={() =>
addHelper(helper, mode === BindingMode.JavaScript)}
>
<span class="binding__label">{helper.displayText}</span>
<span class="binding__typeWrap">

View File

@ -1,10 +1,10 @@
import { getManifest, helpersToRemoveForJs } from "@budibase/string-templates"
import { Helper } from "@budibase/types"
export function handlebarsCompletions() {
export function handlebarsCompletions(): Helper[] {
const manifest = getManifest()
return Object.keys(manifest).flatMap(key =>
Object.entries(manifest[key]).map(([helperName, helperConfig]) => ({
return Object.values(manifest).flatMap(helpersObj =>
Object.entries(helpersObj).map<Helper>(([helperName, helperConfig]) => ({
text: helperName,
path: helperName,
example: helperConfig.example,
@ -14,6 +14,7 @@ export function handlebarsCompletions() {
allowsJs:
!helperConfig.requiresBlock &&
!helpersToRemoveForJs.includes(helperName),
args: helperConfig.args,
}))
)
}

View File

@ -2,9 +2,7 @@
import { getContext } from "svelte"
import { Pagination, ProgressCircle } from "@budibase/bbui"
import { fetchData, QueryUtils } from "@budibase/frontend-core"
import {
LogicalOperator,
EmptyFilterOption,
import type {
TableSchema,
SortOrder,
SearchFilters,
@ -14,6 +12,7 @@
GroupUserDatasource,
DataFetchOptions,
} from "@budibase/types"
import { LogicalOperator, EmptyFilterOption } from "@budibase/types"
type ProviderDatasource = Exclude<
DataFetchDatasource,

View File

@ -4,7 +4,7 @@
import { Utils } from "@budibase/frontend-core"
import FormBlockWrapper from "./FormBlockWrapper.svelte"
import { get } from "svelte/store"
import { TableSchema, UIDatasource } from "@budibase/types"
import type { TableSchema, UIDatasource } from "@budibase/types"
type Field = { name: string; active: boolean }

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { getContext } from "svelte"
import { Icon } from "@budibase/bbui"
import { UIComponentError } from "@budibase/types"
import type { UIComponentError } from "@budibase/types"
import ComponentErrorStateCta from "./ComponentErrorStateCTA.svelte"
export let componentErrors: UIComponentError[] | undefined

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { getContext } from "svelte"
import { UIComponentError } from "@budibase/types"
import type { UIComponentError } from "@budibase/types"
export let error: UIComponentError | undefined

View File

@ -6,7 +6,7 @@
import { findComponentById } from "@/utils/components.js"
import { isGridEvent } from "@/utils/grid"
import { DNDPlaceholderID } from "@/constants"
import { Component } from "@budibase/types"
import type { Component } from "@budibase/types"
type ChildCoords = {
placeholder: boolean

View File

@ -1,7 +1,19 @@
export interface EnrichedBinding {
value: string
valueHTML: string
runtimeBinding: string
readableBinding: string
type?: null | string
icon?: string
category: string
display?: { name: string; type: string }
fieldSchema?: {
name: string
tableId: string
type: string
subtype?: string
prefixKeys?: string
}
}
export enum BindingMode {

View File

@ -1,6 +1,9 @@
export interface Helper {
label: string
displayText: string
example: string
description: string
args: any[]
requiresBlock?: boolean
allowsJs: boolean
}