pass field values in binding drawer

This commit is contained in:
Martin McKeaveney 2021-01-14 14:22:24 +00:00
parent 267e85c2bf
commit 1b51113c44
10 changed files with 121 additions and 114 deletions

View File

@ -9,6 +9,7 @@ const INITIAL_BACKEND_UI_STATE = {
roles: [],
datasources: [],
queries: [],
integrations: {},
selectedDatabase: {},
selectedTable: {},
draftTable: {},
@ -27,11 +28,15 @@ export const getBackendUiStore = () => {
const datasources = await datasourcesResponse.json()
const queriesResponse = await api.get(`/api/queries`)
const queries = await queriesResponse.json()
const integrationsResponse = await api.get("/api/integrations")
const integrations = await integrationsResponse.json()
store.update(state => {
state.selectedDatabase = db
state.tables = tables
state.datasources = datasources
state.queries = queries
state.integrations = integrations
return state
})
},
@ -132,6 +137,7 @@ export const getBackendUiStore = () => {
state.selectedQueryId = json._id
return state
})
return json
},
select: queryId =>
store.update(state => {

View File

@ -1,26 +1,33 @@
<script>
import { onMount } from "svelte"
import { backendUiStore } from "builderStore"
import { Input, TextArea, Spacer } from "@budibase/bbui"
import api from "builderStore/api"
import ICONS from "../icons"
const INTEGRATION_ICON_MAP = {
POSTGRES: "ri-database-2-line",
}
export let integration = {}
let integrationsPromise = fetchIntegrations()
let selectedIntegrationConfig
let schema
let integrations = []
async function fetchIntegrations() {
const response = await api.get("/api/integrations")
const json = await response.json()
integrations = json
return json
}
function selectIntegration(integrationType) {
schema = integrations[integrationType].datasource
integration = {
type: integrationType,
...Object.keys(schema).reduce(
(acc, next) => ({ ...acc, [next]: schema[next].default }),
{}
),
}
}
onMount(() => {
fetchIntegrations()
})
@ -32,18 +39,7 @@
<div
class="integration hoverable"
class:selected={integration.type === integrationType}
on:click={() => {
selectedIntegrationConfig = integrations[integrationType].datasource
integration = { type: integrationType, ...Object.keys(selectedIntegrationConfig).reduce(
(acc, next) => {
return {
...acc,
[next]: selectedIntegrationConfig[next].default,
}
},
{}
) }
}}>
on:click={() => selectIntegration(integrationType)}>
<svelte:component
this={ICONS[integrationType]}
height="100"
@ -53,11 +49,11 @@
{/each}
</div>
{#if selectedIntegrationConfig}
{#each Object.keys(selectedIntegrationConfig) as configKey}
{#if schema}
{#each Object.keys(schema) as configKey}
<Input
thin
type={selectedIntegrationConfig[configKey].type}
type={schema[configKey].type}
label={configKey}
bind:value={integration[configKey]} />
<Spacer medium />

View File

@ -11,6 +11,7 @@
export let fields = {}
export let schema
export let editable
let customSchema = {}
let draftField = {}
@ -29,12 +30,13 @@
{#each Object.keys(schema.fields) as field}
<Label extraSmall grey>{field}</Label>
<Input
disabled={!editable}
type={schema.fields[field]?.type}
required={schema.fields[field]?.required}
bind:value={fields[field]} />
<Spacer medium />
{/each}
{#if schema.customisable}
{#if schema.customisable && editable}
<Spacer large />
<Label>Add Custom Field</Label>
{#each Object.keys(customSchema) as field}

View File

@ -40,8 +40,8 @@
<div />
{/if}
{#each parameters as parameter, idx}
<Input thin bind:value={parameter.name} />
<Input thin bind:value={parameter.default} />
<Input thin disabled={bindable} bind:value={parameter.name} />
<Input thin disabled={bindable} bind:value={parameter.default} />
{#if bindable}
<BindableInput
type="string"

View File

@ -1,5 +1,6 @@
<script>
import { onMount } from "svelte"
import { goto } from "@sveltech/routify"
import {
Select,
Button,
@ -55,8 +56,9 @@
{}
)
$: datasourceType = datasource.source
$: datasourceType && fetchQueryConfig()
$: datasourceType = datasource?.source
$: config = $backendUiStore.integrations[datasourceType]?.query
$: shouldShowQueryConfig = config && query.queryVerb && query.queryType
@ -69,17 +71,6 @@
fields = fields
}
async function fetchQueryConfig() {
try {
const response = await api.get(`/api/integrations/${datasource.source}`)
const json = await response.json()
config = json.query
} catch (err) {
notifier.danger("Error fetching integration configuration.")
console.error(err)
}
}
async function previewQuery() {
try {
const response = await api.post(`/api/queries/preview`, {
@ -115,8 +106,12 @@
async function saveQuery() {
try {
await backendUiStore.actions.queries.save(query.datasourceId, query)
const { _id } = await backendUiStore.actions.queries.save(
query.datasourceId,
query
)
notifier.success(`Query saved successfully.`)
$goto(`../../${_id}`)
} catch (err) {
console.error(err)
notifier.danger(`Error creating query. ${err.message}`)
@ -161,9 +156,10 @@
<Spacer medium />
<IntegrationQueryEditor
schema={config[query.queryVerb][query.queryType]}
{query}
bind:parameters />
schema={config[query.queryVerb][query.queryType]}
bind:parameters
/>
<Spacer medium />

View File

@ -1,18 +1,23 @@
<script>
import CodeMirror from "./codemirror"
import { onMount, createEventDispatcher } from "svelte"
import { themeStore } from "builderStore"
const dispatch = createEventDispatcher()
const THEMES = {
DARK: "tomorrow-night-eighties",
LIGHT: "default",
}
export let value = ""
export let readonly = false
export let errorLoc = null
export let readOnly = false
export let lineNumbers = true
export let tab = true
export let mode
let w
let h
let width
let height
// We have to expose set and update methods, rather
// than making this state-driven through props,
@ -72,43 +77,10 @@
let error_line
let destroyed = false
$: if (editor && w && h) {
$: if (editor && width && height) {
editor.refresh()
}
$: {
if (marker) marker.clear()
if (errorLoc) {
const line = errorLoc.line - 1
const ch = errorLoc.column
marker = editor.markText(
{ line, ch },
{ line, ch: ch + 1 },
{
className: "error-loc",
}
)
error_line = line
} else {
error_line = null
}
}
let previous_error_line
$: if (editor) {
if (previous_error_line != null) {
editor.removeLineClass(previous_error_line, "wrap", "error-line")
}
if (error_line && error_line !== previous_error_line) {
editor.addLineClass(error_line, "wrap", "error-line")
previous_error_line = error_line
}
}
onMount(() => {
createEditor(mode).then(() => {
if (editor) editor.setValue(value || "")
@ -137,9 +109,10 @@
mode: modes[mode] || {
name: mode,
},
readOnly: readonly,
readOnly,
autoCloseBrackets: true,
autoCloseTags: true,
theme: $themeStore.darkMode ? THEMES.DARK : THEMES.LIGHT,
}
if (!tab)
@ -182,6 +155,7 @@
}
:global(.CodeMirror) {
height: auto !important;
border-radius: var(--border-radius-m);
font-family: var(--font-sans) !important;
}

View File

@ -1,5 +1,7 @@
import CodeMirror from "codemirror"
import "codemirror/lib/codemirror.css"
import "codemirror/theme/tomorrow-night-eighties.css"
import "codemirror/theme/neo.css"
import "codemirror/mode/sql/sql"
import "codemirror/mode/css/css"
import "codemirror/mode/handlebars/handlebars"

View File

@ -1,4 +1,5 @@
<script>
import { onMount } from "svelte"
import { TextArea, Label, Input, Heading, Spacer } from "@budibase/bbui"
import Editor from "./SvelteEditor.svelte"
import ParameterBuilder from "./QueryParameterBuilder.svelte"
@ -12,14 +13,17 @@
export let query
export let schema
export let editable = true
function updateQuery({ detail }) {
query.fields[schema.type] = detail.value
}
</script>
<ParameterBuilder bind:parameters={query.parameters} bindable={false} />
<Spacer large />
{#if editable}
<ParameterBuilder bind:parameters={query.parameters} bindable={false} />
<Spacer large />
{/if}
<Heading extraSmall black>Query</Heading>
<Spacer large />
@ -30,6 +34,7 @@
label="Query"
mode="sql"
on:change={updateQuery}
readOnly={!editable}
value={query.fields.sql} />
{:else if schema.type === QueryTypes.JSON}
<Spacer large />
@ -37,8 +42,9 @@
label="Query"
mode="json"
on:change={updateQuery}
readOnly={!editable}
value={query.fields.json} />
{:else if schema.type === QueryTypes.FIELDS}
<FieldsBuilder bind:fields={query.fields} {schema} />
<FieldsBuilder bind:fields={query.fields} {schema} {editable} />
{/if}
{/if}

View File

@ -5,6 +5,7 @@
import { notifier } from "builderStore/store/notifications"
import BottomDrawer from "components/common/BottomDrawer.svelte"
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
import IntegrationQueryEditor from "components/integration/index.svelte"
import fetchBindableProperties from "../../builderStore/fetchBindableProperties"
const dispatch = createEventDispatcher()
@ -13,18 +14,6 @@
export let value = {}
function handleSelected(selected) {
dispatch("change", selected)
dropdownRight.hide()
}
function openBindingDrawer() {
bindingDrawerOpen = true
}
function closeDatabindingDrawer() {
bindingDrawerOpen = false
}
$: tables = $backendUiStore.tables.map(m => ({
label: m.name,
@ -78,6 +67,24 @@
type: "link",
}
})
function handleSelected(selected) {
dispatch("change", selected)
dropdownRight.hide()
}
function openBindingDrawer() {
bindingDrawerOpen = true
}
function closeDatabindingDrawer() {
bindingDrawerOpen = false
}
function fetchDatasourceSchema(query) {
const source = $backendUiStore.datasources.find(ds => ds._id === query.datasourceId).source
return $backendUiStore.integrations[source].query[query.queryVerb][query.queryType];
}
</script>
<div
@ -98,11 +105,18 @@
}}>Save</Button>
</div>
<div class="drawer-contents" slot="body">
<pre>{value.queryString}</pre>
<ParameterBuilder
bind:customParams={value.queryParams}
parameters={value.parameters || []}
bindings={queryBindableProperties} />
<IntegrationQueryEditor
query={value}
schema={fetchDatasourceSchema(value)}
editable={false}
/>
<Spacer large />
{#if value.parameters.length > 0}
<ParameterBuilder
bind:customParams={value.queryParams}
parameters={value.parameters}
bindings={queryBindableProperties} />
{/if}
</div>
</BottomDrawer>
{/if}
@ -229,6 +243,8 @@
.drawer-contents {
padding: var(--spacing-xl);
height: 40vh;
overflow-y: auto;
}
i {

View File

@ -17,24 +17,33 @@
}
}
$: {
if ($params.query !== "new") {
query = $backendUiStore.queries.find(query => query._id === $params.query)
} else {
// New query
query = {
datasourceId: $params.selectedDatasource,
name: "New Query",
parameters: [],
fields: {},
}
}
$: selectedQuery = $backendUiStore.queries.find(
query => query._id === $backendUiStore.selectedQueryId
) || {
datasourceId: $params.selectedDatasource,
name: "New Query",
parameters: [],
fields: {},
}
// $: {
// if ($params.query !== "new") {
// query = $backendUiStore.queries.find(query => query._id === $params.query)
// } else {
// // New query
// query = {
// datasourceId: $params.selectedDatasource,
// name: "New Query",
// parameters: [],
// fields: {},
// }
// }
// }
</script>
<section>
{#if $backendUiStore.selectedDatabase._id && query}
<QueryInterface {query} />
{#if $backendUiStore.selectedDatabase._id && selectedQuery}
<QueryInterface query={selectedQuery} />
{/if}
</section>