Merge pull request #15590 from Budibase/BUDI-9068/type-sidepanel
Type sidepanel
This commit is contained in:
commit
cf84c79c6e
|
@ -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,
|
||||
|
|
|
@ -27,7 +27,7 @@ export type UpdateHandler = (
|
|||
|
||||
interface Opts {
|
||||
anchor?: HTMLElement
|
||||
align: PopoverAlignment
|
||||
align: PopoverAlignment | `${PopoverAlignment}`
|
||||
maxHeight?: number
|
||||
maxWidth?: number
|
||||
minWidth?: number
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -422,7 +422,7 @@
|
|||
{context}
|
||||
addHelper={onSelectHelper}
|
||||
addBinding={onSelectBinding}
|
||||
mode={editorMode}
|
||||
{mode}
|
||||
/>
|
||||
{:else if sidePanel === SidePanel.Evaluation}
|
||||
<EvaluationSidePanel
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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,
|
||||
}))
|
||||
)
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
export interface Helper {
|
||||
label: string
|
||||
displayText: string
|
||||
example: string
|
||||
description: string
|
||||
args: any[]
|
||||
requiresBlock?: boolean
|
||||
allowsJs: boolean
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue