binding data context in component
This commit is contained in:
parent
8e40f4b5f8
commit
102b7ce61f
|
@ -1,43 +0,0 @@
|
|||
<script>
|
||||
import {
|
||||
DropdownMenu,
|
||||
TextButton as Button,
|
||||
Icon,
|
||||
Modal,
|
||||
ModalContent,
|
||||
} from "@budibase/bbui"
|
||||
import { backendUiStore } from "builderStore"
|
||||
import api from "builderStore/api"
|
||||
import EditIntegrationConfig from "../modals/EditIntegrationConfig.svelte"
|
||||
|
||||
export let table
|
||||
|
||||
$: console.log("The table config is", table)
|
||||
|
||||
let modal
|
||||
|
||||
// TODO: revisit
|
||||
async function saveTable() {
|
||||
const SAVE_TABLE_URL = `/api/tables`
|
||||
const response = await api.post(SAVE_TABLE_URL, table)
|
||||
const savedTable = await response.json()
|
||||
await backendUiStore.actions.tables.fetch()
|
||||
backendUiStore.actions.tables.select(savedTable)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Button text small on:click={modal.show}>
|
||||
<Icon name="edit" />
|
||||
Configure Datasource
|
||||
</Button>
|
||||
</div>
|
||||
<Modal bind:this={modal}>
|
||||
<ModalContent
|
||||
confirmText="Save"
|
||||
cancelText="Cancel"
|
||||
onConfirm={saveTable}
|
||||
title={'Datasource Configuration'}>
|
||||
<EditIntegrationConfig onClosed={modal.hide} bind:table />
|
||||
</ModalContent>
|
||||
</Modal>
|
|
@ -3,15 +3,19 @@
|
|||
import Portal from "svelte-portal"
|
||||
|
||||
export let title
|
||||
export let onClose
|
||||
export let onClose = () => {}
|
||||
</script>
|
||||
|
||||
<Portal>
|
||||
<section class="drawer" transition:slide>
|
||||
{#if title}
|
||||
<heading>{title}</heading>
|
||||
{/if}
|
||||
<slot />
|
||||
<header>
|
||||
{title}
|
||||
<div class="controls">
|
||||
<slot name="buttons" />
|
||||
<i class="ri-close-fill close" on:click={onClose} />
|
||||
</div>
|
||||
</header>
|
||||
<slot name="body" />
|
||||
</section>
|
||||
</Portal>
|
||||
|
||||
|
@ -20,10 +24,28 @@
|
|||
height: 50vh;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 97%;
|
||||
width: 100vw;
|
||||
background: var(--background);
|
||||
padding: var(--spacing-xl);
|
||||
border-top: var(--border-light);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border: var(--border-light);
|
||||
padding: var(--spacing-s);
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-gap: var(--spacing-m);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.close {
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -44,4 +44,7 @@
|
|||
background: var(--background);
|
||||
border-radius: var(--border-radius-m);
|
||||
}
|
||||
:global(.CodeMirror) {
|
||||
border-radius: var(--border-radius-m);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { TextArea, Label, Input, Heading } from "@budibase/bbui"
|
||||
import { Button, TextArea, Label, Input, Heading } from "@budibase/bbui"
|
||||
import Editor from "./QueryEditor.svelte"
|
||||
import BindableInput from "components/userInterface/BindableInput.svelte"
|
||||
|
||||
|
@ -17,26 +17,28 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Heading extraSmall black>Parameters</Heading>
|
||||
<div class="parameters">
|
||||
<Label extraSmall grey>Parameter Name</Label>
|
||||
<Label extraSmall grey>Default</Label>
|
||||
<Label extraSmall grey>Value</Label>
|
||||
<div />
|
||||
{#each parameters as parameter, idx}
|
||||
<Input thin bind:value={parameter.name} />
|
||||
<Input thin bind:value={parameter.default} />
|
||||
<BindableInput
|
||||
type="string"
|
||||
thin
|
||||
bind:value={customParams[parameter.name]}
|
||||
{bindings} />
|
||||
<i
|
||||
class="ri-close-circle-line delete"
|
||||
on:click={() => deleteQueryParameter(idx)} />
|
||||
{/each}
|
||||
</div>
|
||||
<i class="ri-add-circle-line add" on:click={newQueryParameter} />
|
||||
<section>
|
||||
<Heading extraSmall black>Parameters</Heading>
|
||||
<div class="parameters">
|
||||
<Label extraSmall grey>Parameter Name</Label>
|
||||
<Label extraSmall grey>Default</Label>
|
||||
<Label extraSmall grey>Value</Label>
|
||||
<div />
|
||||
{#each parameters as parameter, idx}
|
||||
<Input thin bind:value={parameter.name} />
|
||||
<Input thin bind:value={parameter.default} />
|
||||
<BindableInput
|
||||
type="string"
|
||||
thin
|
||||
bind:value={customParams[parameter.name]}
|
||||
{bindings} />
|
||||
<i
|
||||
class="ri-close-circle-line delete"
|
||||
on:click={() => deleteQueryParameter(idx)} />
|
||||
{/each}
|
||||
</div>
|
||||
<Button thin secondary on:click={newQueryParameter}>New Parameter</Button>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.parameters {
|
||||
|
@ -44,9 +46,6 @@
|
|||
grid-template-columns: 1fr 1fr 1fr 5%;
|
||||
grid-gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.add {
|
||||
margin-top: var(--spacing-m);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { TextArea, Label, Input, Heading } from "@budibase/bbui"
|
||||
import { TextArea, Label, Input, Heading, Spacer } from "@budibase/bbui"
|
||||
import Editor from "./QueryEditor.svelte"
|
||||
import ParameterBuilder from "./QueryParameterBuilder.svelte"
|
||||
|
||||
|
@ -12,5 +12,6 @@
|
|||
|
||||
{#if query.queryType === QueryTypes.SQL}
|
||||
<ParameterBuilder bind:parameters={query.parameters} />
|
||||
<Spacer large />
|
||||
<Editor label="Query" bind:value={query.queryString} />
|
||||
{/if}
|
||||
|
|
|
@ -1,35 +1,62 @@
|
|||
<script>
|
||||
import BottomDrawer from "components/common/BottomDrawer.svelte"
|
||||
import { store, backendUiStore } from "builderStore"
|
||||
import { Button } from "@budibase/bbui"
|
||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
||||
import { slide } from "svelte/transition"
|
||||
import QueryInterface from "components/integration/QueryViewer.svelte"
|
||||
import fetchBindableProperties from "builderStore/fetchBindableProperties"
|
||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||
|
||||
$: query = $backendUiStore.queries.find(
|
||||
query => query._id === $backendUiStore.selectedQueryId
|
||||
)
|
||||
export let query
|
||||
export let parameters = {}
|
||||
|
||||
$: console.log("CUSTOM PARAMS", parameters)
|
||||
|
||||
$: bindableProperties = fetchBindableProperties({
|
||||
componentInstanceId: $store.selectedComponentId,
|
||||
components: $store.components,
|
||||
screen: $currentAsset,
|
||||
tables: $backendUiStore.tables,
|
||||
}).map(property => ({
|
||||
...property,
|
||||
category: property.type === "instance" ? "Component" : "Table",
|
||||
label: property.readableBinding,
|
||||
path: property.runtimeBinding,
|
||||
}))
|
||||
|
||||
function closeDatabindingDrawer() {
|
||||
store.update(state => {
|
||||
state.bindingDrawerVisible = false
|
||||
state.bottomDrawerVisible = false
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
function saveComponentQuery() {
|
||||
// save the parameters to the datasource of the component
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if query}
|
||||
<BottomDrawer>
|
||||
<div class="drawer-contents">
|
||||
<i class="ri-close-fill close" on:click={closeDatabindingDrawer} />
|
||||
<QueryInterface {query} />
|
||||
<BottomDrawer title={'Query'} onClose={closeDatabindingDrawer}>
|
||||
<div slot="buttons">
|
||||
<Button blue thin on:click={saveComponentQuery}>Save</Button>
|
||||
</div>
|
||||
<div class="drawer-contents" slot="body">
|
||||
<pre>{query.queryString}</pre>
|
||||
<ParameterBuilder
|
||||
bind:customParams={parameters}
|
||||
parameters={query.parameters}
|
||||
bindings={bindableProperties} />
|
||||
</div>
|
||||
</BottomDrawer>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
i {
|
||||
position: absolute;
|
||||
top: var(--spacing-xl);
|
||||
right: var(--spacing-xl);
|
||||
font-size: var(--font-size-m);
|
||||
.drawer-contents {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-template-columns: 20% 1fr;
|
||||
grid-gap: var(--spacing-m);
|
||||
height: 100%;
|
||||
padding: var(--spacing-xl);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
<script>
|
||||
import {
|
||||
Button,
|
||||
TextButton,
|
||||
Body,
|
||||
DropdownMenu,
|
||||
ModalContent,
|
||||
} from "@budibase/bbui"
|
||||
import { AddIcon, ArrowDownIcon } from "components/common/Icons/"
|
||||
import actionTypes from "./actions"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const eventTypeKey = "##eventHandlerType"
|
||||
|
||||
export let event
|
||||
|
||||
let addActionButton
|
||||
let addActionDropdown
|
||||
let selectedAction
|
||||
|
||||
let draftEventHandler = { parameters: [] }
|
||||
|
||||
$: actions = event || []
|
||||
$: selectedActionComponent =
|
||||
selectedAction &&
|
||||
actionTypes.find(t => t.name === selectedAction[eventTypeKey]).component
|
||||
|
||||
const updateEventHandler = (updatedHandler, index) => {
|
||||
actions[index] = updatedHandler
|
||||
}
|
||||
|
||||
const deleteAction = index => {
|
||||
actions.splice(index, 1)
|
||||
actions = actions
|
||||
}
|
||||
|
||||
const addAction = actionType => () => {
|
||||
const newAction = {
|
||||
parameters: {},
|
||||
[eventTypeKey]: actionType.name,
|
||||
}
|
||||
actions.push(newAction)
|
||||
selectedAction = newAction
|
||||
actions = actions
|
||||
addActionDropdown.hide()
|
||||
}
|
||||
|
||||
const selectAction = action => () => {
|
||||
selectedAction = action
|
||||
}
|
||||
|
||||
const saveEventData = () => {
|
||||
dispatch("change", actions)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="actions-container">
|
||||
<div class="actions-list">
|
||||
<div>
|
||||
<div bind:this={addActionButton}>
|
||||
<TextButton text small blue on:click={addActionDropdown.show}>
|
||||
<div style="height: 20px; width: 20px;">
|
||||
<AddIcon />
|
||||
</div>
|
||||
Add Action
|
||||
</TextButton>
|
||||
</div>
|
||||
<DropdownMenu
|
||||
bind:this={addActionDropdown}
|
||||
anchor={addActionButton}
|
||||
align="right">
|
||||
<div class="available-actions-container">
|
||||
{#each actionTypes as actionType}
|
||||
<div class="available-action" on:click={addAction(actionType)}>
|
||||
<span>{actionType.name}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
{#if actions && actions.length > 0}
|
||||
{#each actions as action, index}
|
||||
<div class="action-container">
|
||||
<div class="action-header" on:click={selectAction(action)}>
|
||||
<span class:selected={action === selectedAction}>
|
||||
{index + 1}. {action[eventTypeKey]}
|
||||
</span>
|
||||
<!-- <Body small lh>{index + 1}. {action[eventTypeKey]}</Body> -->
|
||||
<!-- <div class="row-expander" class:rotate={action !== selectedAction}>
|
||||
<ArrowDownIcon />
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- {#if action === selectedAction}
|
||||
<div class="selected-action-container">
|
||||
<svelte:component
|
||||
this={selectedActionComponent}
|
||||
parameters={selectedAction.parameters} />
|
||||
<div class="delete-action-button">
|
||||
<TextButton text medium on:click={() => deleteAction(index)}>
|
||||
Delete
|
||||
</TextButton>
|
||||
</div>
|
||||
</div>
|
||||
{/if} -->
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="action-config">
|
||||
{#if selectedAction}
|
||||
<div class="selected-action-container">
|
||||
<svelte:component
|
||||
this={selectedActionComponent}
|
||||
parameters={selectedAction.parameters} />
|
||||
<div class="delete-action-button">
|
||||
<!-- <TextButton text medium on:click={() => deleteAction(index)}>
|
||||
Delete
|
||||
</TextButton> -->
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<Button thin blue on:click={saveEventData}>Save</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="https://docs.budibase.com">Learn more about Actions</a>
|
||||
|
||||
<style>
|
||||
.action-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-header > span {
|
||||
margin-bottom: var(--spacing-m);
|
||||
}
|
||||
|
||||
.action-header > span:hover,
|
||||
.selected {
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.actions-list {
|
||||
border: var(--border-light);
|
||||
}
|
||||
|
||||
.available-action {
|
||||
padding: var(--spacing-s);
|
||||
font-size: var(--font-size-m);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.available-action:hover {
|
||||
background: var(--grey-2);
|
||||
}
|
||||
|
||||
.actions-container {
|
||||
display: grid;
|
||||
grid-gap: var(--spacing-m);
|
||||
grid-template-columns: 15% 1fr;
|
||||
grid-auto-flow: column;
|
||||
min-height: 0;
|
||||
padding-top: 0;
|
||||
border: var(--border-light);
|
||||
border-width: 0 0 1px 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.action-container {
|
||||
border: var(--border-light);
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
|
||||
.selected-action-container {
|
||||
padding-bottom: var(--spacing-s);
|
||||
padding-top: var(--spacing-s);
|
||||
}
|
||||
|
||||
.delete-action-button {
|
||||
padding-top: var(--spacing-l);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
a {
|
||||
flex: 1;
|
||||
color: var(--grey-5);
|
||||
font-size: var(--font-size-s);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--blue);
|
||||
}
|
||||
</style>
|
|
@ -1,176 +0,0 @@
|
|||
<script>
|
||||
import {
|
||||
Button,
|
||||
TextButton,
|
||||
Body,
|
||||
DropdownMenu,
|
||||
ModalContent,
|
||||
} from "@budibase/bbui"
|
||||
import { AddIcon, ArrowDownIcon } from "components/common/Icons/"
|
||||
import actionTypes from "./actions"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const eventTypeKey = "##eventHandlerType"
|
||||
|
||||
export let event
|
||||
|
||||
let addActionButton
|
||||
let addActionDropdown
|
||||
let selectedAction
|
||||
|
||||
let draftEventHandler = { parameters: [] }
|
||||
|
||||
$: actions = event || []
|
||||
$: selectedActionComponent =
|
||||
selectedAction &&
|
||||
actionTypes.find(t => t.name === selectedAction[eventTypeKey]).component
|
||||
|
||||
const updateEventHandler = (updatedHandler, index) => {
|
||||
actions[index] = updatedHandler
|
||||
}
|
||||
|
||||
const deleteAction = index => {
|
||||
actions.splice(index, 1)
|
||||
actions = actions
|
||||
}
|
||||
|
||||
const addAction = actionType => () => {
|
||||
const newAction = {
|
||||
parameters: {},
|
||||
[eventTypeKey]: actionType.name,
|
||||
}
|
||||
actions.push(newAction)
|
||||
selectedAction = newAction
|
||||
actions = actions
|
||||
addActionDropdown.hide()
|
||||
}
|
||||
|
||||
const selectAction = action => () => {
|
||||
selectedAction = action
|
||||
}
|
||||
|
||||
const saveEventData = () => {
|
||||
dispatch("change", actions)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div bind:this={addActionButton}>
|
||||
<TextButton text small blue on:click={addActionDropdown.show}>
|
||||
<div style="height: 20px; width: 20px;">
|
||||
<AddIcon />
|
||||
</div>
|
||||
Add Action
|
||||
</TextButton>
|
||||
</div>
|
||||
<DropdownMenu
|
||||
bind:this={addActionDropdown}
|
||||
anchor={addActionButton}
|
||||
align="right">
|
||||
<div class="available-actions-container">
|
||||
{#each actionTypes as actionType}
|
||||
<div class="available-action" on:click={addAction(actionType)}>
|
||||
<span>{actionType.name}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
<div class="actions-container">
|
||||
{#if actions && actions.length > 0}
|
||||
{#each actions as action, index}
|
||||
<div class="action-container">
|
||||
<div class="action-header" on:click={selectAction(action)}>
|
||||
<Body small lh>{index + 1}. {action[eventTypeKey]}</Body>
|
||||
<div class="row-expander" class:rotate={action !== selectedAction}>
|
||||
<ArrowDownIcon />
|
||||
</div>
|
||||
</div>
|
||||
{#if action === selectedAction}
|
||||
<div class="selected-action-container">
|
||||
<svelte:component
|
||||
this={selectedActionComponent}
|
||||
parameters={selectedAction.parameters} />
|
||||
<div class="delete-action-button">
|
||||
<TextButton text medium on:click={() => deleteAction(index)}>
|
||||
Delete
|
||||
</TextButton>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
<Button thin blue on:click={saveEventData}>Save</Button>
|
||||
</div>
|
||||
|
||||
<a href="https://docs.budibase.com">Learn more about Actions</a>
|
||||
|
||||
<style>
|
||||
.action-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-header > p {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.row-expander {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.available-action {
|
||||
padding: var(--spacing-s);
|
||||
font-size: var(--font-size-m);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.available-action:hover {
|
||||
background: var(--grey-2);
|
||||
}
|
||||
|
||||
.actions-container {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
padding-top: 0;
|
||||
border: var(--border-light);
|
||||
border-width: 0 0 1px 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.action-container {
|
||||
border: var(--border-light);
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
|
||||
.selected-action-container {
|
||||
padding-bottom: var(--spacing-s);
|
||||
padding-top: var(--spacing-s);
|
||||
}
|
||||
|
||||
.delete-action-button {
|
||||
padding-top: var(--spacing-l);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
a {
|
||||
flex: 1;
|
||||
color: var(--grey-5);
|
||||
font-size: var(--font-size-s);
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
.rotate :global(svg) {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
</style>
|
|
@ -2,7 +2,7 @@
|
|||
import { Button, Modal } from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { store } from "builderStore"
|
||||
import EventEditorModal from "./EventEditorModal.svelte"
|
||||
import EventEditor from "./EventEditor.svelte"
|
||||
import BottomDrawer from "components/common/BottomDrawer.svelte"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
@ -20,7 +20,12 @@
|
|||
<Button secondary small on:click={showDrawer}>Define Actions</Button>
|
||||
|
||||
{#if drawerVisible}
|
||||
<BottomDrawer>
|
||||
<EventEditorModal event={value} eventType={name} on:change />
|
||||
<BottomDrawer title={'Actions'} onClose={() => (drawerVisible = false)}>
|
||||
<heading slot="buttons">
|
||||
<Button thin blue>Save</Button>
|
||||
</heading>
|
||||
<div slot="body">
|
||||
<EventEditor event={value} eventType={name} on:change />
|
||||
</div>
|
||||
</BottomDrawer>
|
||||
{/if}
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
import { Button, Icon, DropdownMenu, Spacer, Heading } from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
||||
// import DataBindingDrawer from "components/userInterface/DataBindingDrawer/index.svelte"
|
||||
import BottomDrawer from "components/common/BottomDrawer.svelte"
|
||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||
import fetchBindableProperties from "../../builderStore/fetchBindableProperties"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let anchorRight, dropdownRight
|
||||
let bindingDrawerOpen
|
||||
|
||||
export let value = {}
|
||||
|
||||
|
@ -15,14 +19,11 @@
|
|||
}
|
||||
|
||||
function openBindingDrawer() {
|
||||
backendUiStore.update(state => {
|
||||
state.selectedQueryId = value._id
|
||||
return state
|
||||
})
|
||||
store.update(state => {
|
||||
state.bottomDrawerVisible = true
|
||||
return state
|
||||
})
|
||||
bindingDrawerOpen = true
|
||||
}
|
||||
|
||||
function closeDatabindingDrawer() {
|
||||
bindingDrawerOpen = false
|
||||
}
|
||||
|
||||
$: tables = $backendUiStore.tables.map(m => ({
|
||||
|
@ -47,6 +48,7 @@
|
|||
name: query.name,
|
||||
...query,
|
||||
schema: query.schema,
|
||||
parameters: query.parameters,
|
||||
type: "query",
|
||||
}))
|
||||
|
||||
|
@ -57,6 +59,15 @@
|
|||
tables: $backendUiStore.tables,
|
||||
})
|
||||
|
||||
$: queryBindableProperties = bindableProperties.map(property => ({
|
||||
...property,
|
||||
category: property.type === "instance" ? "Component" : "Table",
|
||||
label: property.readableBinding,
|
||||
path: property.runtimeBinding,
|
||||
}))
|
||||
|
||||
$: console.log("selected", value)
|
||||
|
||||
$: links = bindableProperties
|
||||
.filter(x => x.fieldSchema?.type === "link")
|
||||
.map(property => {
|
||||
|
@ -78,9 +89,6 @@
|
|||
<span>{value.label ? value.label : 'Table / View / Query'}</span>
|
||||
<Icon name="arrowdown" />
|
||||
</div>
|
||||
{#if value.type === "query"}
|
||||
<i class="ri-settings-3-line" on:click={openBindingDrawer} />
|
||||
{/if}
|
||||
<DropdownMenu bind:this={dropdownRight} anchor={anchorRight}>
|
||||
<div class="dropdown">
|
||||
<div class="title">
|
||||
|
@ -138,6 +146,25 @@
|
|||
</div>
|
||||
</DropdownMenu>
|
||||
|
||||
{#if value.type === "query"}
|
||||
<Button blue on:click={openBindingDrawer}/>
|
||||
{#if bindingDrawerOpen}
|
||||
<BottomDrawer title={'Query'} onClose={closeDatabindingDrawer}>
|
||||
<div slot="buttons">
|
||||
<Button blue thin on:click={() => handleSelected(value)}>Save</Button>
|
||||
</div>
|
||||
<div class="drawer-contents" slot="body">
|
||||
<pre>{value.queryString}</pre>
|
||||
<ParameterBuilder
|
||||
bind:customParams={value.queryParams}
|
||||
parameters={value.parameters || []}
|
||||
bindings={queryBindableProperties} />
|
||||
</div>
|
||||
</BottomDrawer>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
|
||||
<style>
|
||||
.dropdownbutton {
|
||||
background-color: var(--grey-2);
|
||||
|
@ -199,4 +226,8 @@
|
|||
li:hover {
|
||||
background-color: var(--grey-4);
|
||||
}
|
||||
|
||||
.drawer-contents {
|
||||
padding: var(--spacing-xl);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
import ComponentPropertiesPanel from "components/userInterface/ComponentPropertiesPanel.svelte"
|
||||
import ComponentSelectionList from "components/userInterface/ComponentSelectionList.svelte"
|
||||
import FrontendNavigatePane from "components/userInterface/FrontendNavigatePane.svelte"
|
||||
import DataBindingDrawer from "components/userInterface/DataBindingDrawer/index.svelte"
|
||||
|
||||
$: instance = $store.appInstance
|
||||
|
||||
|
@ -48,10 +47,6 @@
|
|||
{/if}
|
||||
</div>
|
||||
|
||||
{#if $store.bottomDrawerVisible}
|
||||
<DataBindingDrawer />
|
||||
{/if}
|
||||
|
||||
{#if $selectedComponent != null}
|
||||
<div class="components-pane">
|
||||
<ComponentPropertiesPanel />
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { fetchTableData } from "./tables"
|
||||
import { fetchViewData } from "./views"
|
||||
import { fetchRelationshipData } from "./relationships"
|
||||
import { fetchQueryData } from "./queries"
|
||||
import { executeQuery } from "./queries"
|
||||
import { enrichRows } from "./rows"
|
||||
import { enrichDataBindings } from "../utils/enrichDataBinding"
|
||||
|
||||
/**
|
||||
* Fetches all rows for a particular Budibase data source.
|
||||
|
@ -20,8 +21,12 @@ export const fetchDatasource = async (datasource, dataContext) => {
|
|||
} else if (type === "view") {
|
||||
rows = await fetchViewData(datasource)
|
||||
} else if (type === "query") {
|
||||
// TODO: map to schema
|
||||
return await fetchQueryData(datasource)
|
||||
console.log("Query Datasource", datasource)
|
||||
console.log("Data Context", dataContext)
|
||||
// TODO: You left here
|
||||
const parameters = enrichDataBindings(datasource.queryParams, dataContext)
|
||||
console.log("PARSED PARAMS", parameters)
|
||||
return await executeQuery({ _id: datasource._id, parameters })
|
||||
} else if (type === "link") {
|
||||
const row = dataContext[datasource.providerId]
|
||||
rows = await fetchRelationshipData({
|
||||
|
|
|
@ -1,23 +1,13 @@
|
|||
import API from "./api"
|
||||
|
||||
/**
|
||||
* Fetches all rows from a query.
|
||||
*/
|
||||
export const fetchQueryData = async ({ _id }) => {
|
||||
const response = await API.get({
|
||||
url: `/api/queries/${_id}`,
|
||||
})
|
||||
return response.rows
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a query against an external data connector.
|
||||
*/
|
||||
export const executeQuery = async ({ queryId, params }) => {
|
||||
export const executeQuery = async ({ queryId, parameters }) => {
|
||||
const response = await API.post({
|
||||
url: `/api/queries/${queryId}`,
|
||||
body: {
|
||||
params,
|
||||
parameters,
|
||||
},
|
||||
})
|
||||
return response.rows
|
||||
|
|
|
@ -28,10 +28,13 @@ const navigationHandler = action => {
|
|||
const queryExecutionHandler = async (action, context) => {
|
||||
const { datasourceId, queryId, queryParams } = action.parameters
|
||||
|
||||
// TODO: allow context based bindings for query params
|
||||
const enrichedQueryParameters = enrichDataBindings(queryParams, context)
|
||||
|
||||
await executeQuery({ datasourceId, queryId, params: enrichedQueryParameters })
|
||||
await executeQuery({
|
||||
datasourceId,
|
||||
queryId,
|
||||
parameters: enrichedQueryParameters,
|
||||
})
|
||||
}
|
||||
|
||||
const handlerMap = {
|
||||
|
|
|
@ -81,7 +81,7 @@ exports.execute = async function(ctx) {
|
|||
const queryTemplate = handlebars.compile(query.queryString)
|
||||
|
||||
// TODO: Take the default params into account
|
||||
const parsedQuery = queryTemplate(ctx.request.body.params)
|
||||
const parsedQuery = queryTemplate(ctx.request.body.parameters)
|
||||
|
||||
const Integration = integrations[datasource.source]
|
||||
|
||||
|
@ -94,31 +94,6 @@ exports.execute = async function(ctx) {
|
|||
ctx.body = response
|
||||
}
|
||||
|
||||
exports.fetchQuery = async function(ctx) {
|
||||
const db = new CouchDB(ctx.user.appId)
|
||||
|
||||
const query = await db.get(ctx.params.queryId)
|
||||
|
||||
const datasource = await db.get(query.datasourceId)
|
||||
|
||||
const Integration = integrations[datasource.source]
|
||||
|
||||
if (!Integration) {
|
||||
ctx.throw(400, "Integration type does not exist.")
|
||||
return
|
||||
}
|
||||
|
||||
const rows = await new Integration(
|
||||
datasource.config,
|
||||
query.queryString
|
||||
).query()
|
||||
|
||||
ctx.body = {
|
||||
schema: query.schema,
|
||||
rows,
|
||||
}
|
||||
}
|
||||
|
||||
exports.destroy = async function(ctx) {
|
||||
const db = new CouchDB(ctx.user.appId)
|
||||
await db.destroy(ctx.params.queryId)
|
||||
|
|
|
@ -8,10 +8,9 @@ const router = Router()
|
|||
// TODO: sort out auth so apps have the right permissions
|
||||
router
|
||||
.get("/api/queries", authorized(BUILDER), queryController.fetch)
|
||||
.get("/api/queries/:queryId", authorized(BUILDER), queryController.fetchQuery)
|
||||
.post("/api/queries", authorized(BUILDER), queryController.save)
|
||||
.post("/api/queries/preview", authorized(BUILDER), queryController.preview)
|
||||
.post("/api/queries/:queryId", authorized(BUILDER), queryController.execute)
|
||||
.post("/api/queries/preview", authorized(BUILDER), queryController.preview)
|
||||
.delete("/api/queries/:queryId", authorized(BUILDER), queryController.destroy)
|
||||
|
||||
module.exports = router
|
||||
|
|
Loading…
Reference in New Issue