Remove duplicates
This commit is contained in:
parent
ab6907691f
commit
af6307a608
|
@ -27,7 +27,6 @@
|
||||||
} from "../CodeEditor"
|
} from "../CodeEditor"
|
||||||
import BindingSidePanel from "./BindingSidePanel.svelte"
|
import BindingSidePanel from "./BindingSidePanel.svelte"
|
||||||
import EvaluationSidePanel from "./EvaluationSidePanel.svelte"
|
import EvaluationSidePanel from "./EvaluationSidePanel.svelte"
|
||||||
import SnippetSidePanel from "./SnippetSidePanel.svelte"
|
|
||||||
import { BindingHelpers } from "./utils"
|
import { BindingHelpers } from "./utils"
|
||||||
import { capitalise } from "@/helpers"
|
import { capitalise } from "@/helpers"
|
||||||
import { Utils, JsonFormatter } from "@budibase/frontend-core"
|
import { Utils, JsonFormatter } from "@budibase/frontend-core"
|
||||||
|
@ -74,22 +73,15 @@
|
||||||
const enum SidePanel {
|
const enum SidePanel {
|
||||||
Bindings = "Bindings",
|
Bindings = "Bindings",
|
||||||
Evaluation = "Evaluation",
|
Evaluation = "Evaluation",
|
||||||
Snippets = "Snippets",
|
|
||||||
}
|
}
|
||||||
const SidePanelIcons: Record<SidePanel, string> = {
|
const SidePanelIcons: Record<SidePanel, string> = {
|
||||||
Bindings: "FlashOn",
|
Bindings: "FlashOn",
|
||||||
Evaluation: "Play",
|
Evaluation: "Play",
|
||||||
Snippets: "Code",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$: useSnippets = allowSnippets && !$licensing.isFreePlan
|
$: useSnippets = allowSnippets && !$licensing.isFreePlan
|
||||||
$: editorModeOptions = getModeOptions(allowHBS, allowJS)
|
$: editorModeOptions = getModeOptions(allowHBS, allowJS)
|
||||||
$: sidePanelOptions = getSidePanelOptions(
|
$: sidePanelOptions = getSidePanelOptions(bindings, context)
|
||||||
bindings,
|
|
||||||
context,
|
|
||||||
allowSnippets,
|
|
||||||
mode
|
|
||||||
)
|
|
||||||
$: enrichedBindings = enrichBindings(bindings, context, snippets)
|
$: enrichedBindings = enrichBindings(bindings, context, snippets)
|
||||||
$: usingJS = mode === BindingMode.JavaScript
|
$: usingJS = mode === BindingMode.JavaScript
|
||||||
$: editorMode =
|
$: editorMode =
|
||||||
|
@ -148,12 +140,7 @@
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSidePanelOptions = (
|
const getSidePanelOptions = (bindings: EnrichedBinding[], context: any) => {
|
||||||
bindings: EnrichedBinding[],
|
|
||||||
context: any,
|
|
||||||
useSnippets: boolean,
|
|
||||||
mode: BindingMode | null
|
|
||||||
) => {
|
|
||||||
let options = []
|
let options = []
|
||||||
if (bindings?.length) {
|
if (bindings?.length) {
|
||||||
options.push(SidePanel.Bindings)
|
options.push(SidePanel.Bindings)
|
||||||
|
@ -161,9 +148,6 @@
|
||||||
if (context && Object.keys(context).length > 0) {
|
if (context && Object.keys(context).length > 0) {
|
||||||
options.push(SidePanel.Evaluation)
|
options.push(SidePanel.Evaluation)
|
||||||
}
|
}
|
||||||
if (useSnippets && mode === BindingMode.JavaScript) {
|
|
||||||
options.push(SidePanel.Snippets)
|
|
||||||
}
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,8 +430,6 @@
|
||||||
{evaluating}
|
{evaluating}
|
||||||
expression={editorValue ? editorValue : ""}
|
expression={editorValue ? editorValue : ""}
|
||||||
/>
|
/>
|
||||||
{:else if sidePanel === SidePanel.Snippets}
|
|
||||||
<SnippetSidePanel {addSnippet} {snippets} />
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,278 +0,0 @@
|
||||||
<script>
|
|
||||||
import {
|
|
||||||
Input,
|
|
||||||
Layout,
|
|
||||||
Icon,
|
|
||||||
Popover,
|
|
||||||
Tags,
|
|
||||||
Tag,
|
|
||||||
Body,
|
|
||||||
Button,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import CodeEditor from "@/components/common/CodeEditor/CodeEditor.svelte"
|
|
||||||
import { EditorModes } from "@/components/common/CodeEditor"
|
|
||||||
import SnippetDrawer from "./SnippetDrawer.svelte"
|
|
||||||
import { licensing } from "@/stores/portal"
|
|
||||||
import UpgradeButton from "@/pages/builder/portal/_components/UpgradeButton.svelte"
|
|
||||||
|
|
||||||
export let addSnippet
|
|
||||||
export let snippets
|
|
||||||
|
|
||||||
let search = ""
|
|
||||||
let searching = false
|
|
||||||
let popover
|
|
||||||
let popoverAnchor
|
|
||||||
let hoveredSnippet
|
|
||||||
let hideTimeout
|
|
||||||
let snippetDrawer
|
|
||||||
let editableSnippet
|
|
||||||
|
|
||||||
$: enableSnippets = !$licensing.isFreePlan
|
|
||||||
$: filteredSnippets = getFilteredSnippets(enableSnippets, snippets, search)
|
|
||||||
|
|
||||||
const getFilteredSnippets = (enableSnippets, snippets, search) => {
|
|
||||||
if (!enableSnippets || !snippets?.length) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
if (!search?.length) {
|
|
||||||
return snippets
|
|
||||||
}
|
|
||||||
return snippets.filter(snippet =>
|
|
||||||
snippet.name.toLowerCase().includes(search.toLowerCase())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const showSnippet = (snippet, target) => {
|
|
||||||
stopHidingPopover()
|
|
||||||
popoverAnchor = target
|
|
||||||
hoveredSnippet = snippet
|
|
||||||
popover.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
const hidePopover = () => {
|
|
||||||
hideTimeout = setTimeout(() => {
|
|
||||||
popover.hide()
|
|
||||||
popoverAnchor = null
|
|
||||||
hoveredSnippet = null
|
|
||||||
hideTimeout = null
|
|
||||||
}, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
const stopHidingPopover = () => {
|
|
||||||
if (hideTimeout) {
|
|
||||||
clearTimeout(hideTimeout)
|
|
||||||
hideTimeout = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const startSearching = () => {
|
|
||||||
searching = true
|
|
||||||
search = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
const stopSearching = () => {
|
|
||||||
searching = false
|
|
||||||
search = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
const createSnippet = () => {
|
|
||||||
editableSnippet = null
|
|
||||||
snippetDrawer.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
const editSnippet = (e, snippet) => {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
editableSnippet = snippet
|
|
||||||
snippetDrawer.show()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
||||||
<div class="snippet-side-panel">
|
|
||||||
<Layout noPadding gap="S">
|
|
||||||
<div class="header">
|
|
||||||
{#if enableSnippets}
|
|
||||||
{#if searching}
|
|
||||||
<div class="search-input">
|
|
||||||
<Input
|
|
||||||
placeholder="Search for snippets"
|
|
||||||
autocomplete="off"
|
|
||||||
bind:value={search}
|
|
||||||
autofocus
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Icon
|
|
||||||
size="S"
|
|
||||||
name="Close"
|
|
||||||
hoverable
|
|
||||||
newStyles
|
|
||||||
on:click={stopSearching}
|
|
||||||
/>
|
|
||||||
{:else}
|
|
||||||
<div class="title">Snippets</div>
|
|
||||||
<Icon
|
|
||||||
size="S"
|
|
||||||
name="Search"
|
|
||||||
hoverable
|
|
||||||
newStyles
|
|
||||||
on:click={startSearching}
|
|
||||||
/>
|
|
||||||
<Icon
|
|
||||||
size="S"
|
|
||||||
name="Add"
|
|
||||||
hoverable
|
|
||||||
newStyles
|
|
||||||
on:click={createSnippet}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
{:else}
|
|
||||||
<div class="title">
|
|
||||||
Snippets
|
|
||||||
<Tags>
|
|
||||||
<Tag icon="LockClosed">Premium</Tag>
|
|
||||||
</Tags>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div class="snippet-list">
|
|
||||||
{#if enableSnippets && filteredSnippets?.length}
|
|
||||||
{#each filteredSnippets as snippet}
|
|
||||||
<div
|
|
||||||
class="snippet"
|
|
||||||
on:mouseenter={e => showSnippet(snippet, e.target)}
|
|
||||||
on:mouseleave={hidePopover}
|
|
||||||
on:click={() => addSnippet(snippet)}
|
|
||||||
>
|
|
||||||
{snippet.name}
|
|
||||||
<Icon
|
|
||||||
name="Edit"
|
|
||||||
hoverable
|
|
||||||
newStyles
|
|
||||||
size="S"
|
|
||||||
on:click={e => editSnippet(e, snippet)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
{:else}
|
|
||||||
<div class="upgrade">
|
|
||||||
<Body size="S">
|
|
||||||
Snippets let you create reusable JS functions and values that can
|
|
||||||
all be managed in one place
|
|
||||||
</Body>
|
|
||||||
{#if enableSnippets}
|
|
||||||
<Button cta on:click={createSnippet}>Create snippet</Button>
|
|
||||||
{:else}
|
|
||||||
<UpgradeButton />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Popover
|
|
||||||
align="left-outside"
|
|
||||||
bind:this={popover}
|
|
||||||
anchor={popoverAnchor}
|
|
||||||
minWidth={0}
|
|
||||||
maxWidth={480}
|
|
||||||
maxHeight={480}
|
|
||||||
dismissible={false}
|
|
||||||
on:mouseenter={stopHidingPopover}
|
|
||||||
on:mouseleave={hidePopover}
|
|
||||||
>
|
|
||||||
<div class="snippet-popover">
|
|
||||||
{#key hoveredSnippet}
|
|
||||||
<CodeEditor
|
|
||||||
value={hoveredSnippet.code?.trim()}
|
|
||||||
mode={EditorModes.JS}
|
|
||||||
readonly
|
|
||||||
/>
|
|
||||||
{/key}
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
<SnippetDrawer bind:this={snippetDrawer} snippet={editableSnippet} />
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.snippet-side-panel {
|
|
||||||
border-left: var(--border-light);
|
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Header */
|
|
||||||
.header {
|
|
||||||
height: 53px;
|
|
||||||
padding: 0 var(--spacing-l);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: var(--border-light);
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
gap: var(--spacing-m);
|
|
||||||
background: var(--background);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.header :global(input) {
|
|
||||||
border: none;
|
|
||||||
border-radius: 0;
|
|
||||||
background: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.search-input,
|
|
||||||
.title {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--spacing-m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Upgrade */
|
|
||||||
.upgrade {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--spacing-l);
|
|
||||||
}
|
|
||||||
.upgrade :global(p) {
|
|
||||||
text-align: center;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* List */
|
|
||||||
.snippet-list {
|
|
||||||
padding: 0 var(--spacing-l);
|
|
||||||
padding-bottom: var(--spacing-l);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--spacing-s);
|
|
||||||
}
|
|
||||||
.snippet {
|
|
||||||
font-size: var(--font-size-s);
|
|
||||||
padding: var(--spacing-m);
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: var(--spectrum-global-color-gray-200);
|
|
||||||
transition: background-color 130ms ease-out, color 130ms ease-out,
|
|
||||||
border-color 130ms ease-out;
|
|
||||||
word-wrap: break-word;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.snippet:hover {
|
|
||||||
color: var(--spectrum-global-color-gray-900);
|
|
||||||
background-color: var(--spectrum-global-color-gray-50);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Popover */
|
|
||||||
.snippet-popover {
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -8,5 +8,3 @@ export { default as DrawerBindableSlot } from "./DrawerBindableSlot.svelte"
|
||||||
export { default as EvaluationSidePanel } from "./EvaluationSidePanel.svelte"
|
export { default as EvaluationSidePanel } from "./EvaluationSidePanel.svelte"
|
||||||
export { default as ModalBindableInput } from "./ModalBindableInput.svelte"
|
export { default as ModalBindableInput } from "./ModalBindableInput.svelte"
|
||||||
export { default as ServerBindingPanel } from "./ServerBindingPanel.svelte"
|
export { default as ServerBindingPanel } from "./ServerBindingPanel.svelte"
|
||||||
export { default as SnippetDrawer } from "./SnippetDrawer.svelte"
|
|
||||||
export { default as SnippetSidePanel } from "./SnippetSidePanel.svelte"
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { Icon, Popover, Body, Button } from "@budibase/bbui"
|
import { Icon, Popover, Body, Button } from "@budibase/bbui"
|
||||||
import CodeEditor from "@/components/common/CodeEditor/CodeEditor.svelte"
|
import CodeEditor from "@/components/common/CodeEditor/CodeEditor.svelte"
|
||||||
import { EditorModes } from "@/components/common/CodeEditor"
|
import { EditorModes } from "@/components/common/CodeEditor"
|
||||||
import SnippetDrawer from "../SnippetDrawer.svelte"
|
import SnippetDrawer from "./SnippetDrawer.svelte"
|
||||||
import { licensing } from "@/stores/portal"
|
import { licensing } from "@/stores/portal"
|
||||||
import UpgradeButton from "@/pages/builder/portal/_components/UpgradeButton.svelte"
|
import UpgradeButton from "@/pages/builder/portal/_components/UpgradeButton.svelte"
|
||||||
import type { Snippet } from "@budibase/types"
|
import type { Snippet } from "@budibase/types"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Icon, Tags, Tag } from "@budibase/bbui"
|
import { Icon, Tags, Tag } from "@budibase/bbui"
|
||||||
import { licensing } from "@/stores/portal"
|
import { licensing } from "@/stores/portal"
|
||||||
import SnippetDrawer from "../SnippetDrawer.svelte"
|
import SnippetDrawer from "./SnippetDrawer.svelte"
|
||||||
import type { Snippet } from "@budibase/types"
|
import type { Snippet } from "@budibase/types"
|
||||||
|
|
||||||
$: enableSnippets = !$licensing.isFreePlan
|
$: enableSnippets = !$licensing.isFreePlan
|
||||||
|
|
Loading…
Reference in New Issue