1
0
Fork 0
mirror of synced 2024-09-20 19:33:10 +12:00
budibase/packages/builder/src/components/integration/index.svelte
2022-10-14 08:02:29 +01:00

279 lines
8 KiB
Svelte

<script>
import Editor from "./QueryEditor.svelte"
import FieldsBuilder from "./QueryFieldsBuilder.svelte"
import {
Label,
Input,
Select,
Divider,
Layout,
Icon,
Button,
ActionButton,
} from "@budibase/bbui"
const QueryTypes = {
SQL: "sql",
JSON: "json",
FIELDS: "fields",
}
export let query
export let datasource
export let schema
export let editable = true
export let height = 500
let stepEditors = []
$: urlDisplay =
schema.urlDisplay &&
`${datasource.config.url}${
query.fields.path ? "/" + query.fields.path : ""
}${query.fields.queryString ? "?" + query.fields.queryString : ""}`
function updateQuery({ detail }) {
query.fields[schema.type] = detail.value
}
function updateEditorsOnDelete(deleteIndex) {
for (let i = deleteIndex; i < query.fields.steps?.length - 1; i++) {
stepEditors[i].update(query.fields.steps[i + 1].value?.value)
}
}
function updateEditorsOnSwap(actionIndex, targetIndex) {
const target = query.fields.steps[targetIndex].value?.value
stepEditors[targetIndex].update(
query.fields.steps[actionIndex].value?.value
)
stepEditors[actionIndex].update(target)
}
function setEditorTemplate(fromKey, toKey, index) {
const currentValue = query.fields.steps[index].value?.value
if (
!currentValue ||
currentValue.toString().replace("\\s", "").length < 3 ||
schema.steps.filter(step => step.key === fromKey)[0]?.template ===
currentValue
) {
query.fields.steps[index].value.value = schema.steps.filter(
step => step.key === toKey
)[0]?.template
stepEditors[index].update(query.fields.steps[index].value.value)
}
query.fields.steps[index].key = toKey
}
$: shouldDisplayJsonBox =
schema.type === QueryTypes.JSON &&
query.fields.extra?.actionType !== "pipeline"
</script>
{#if schema}
{#key query._id}
{#if schema.type === QueryTypes.SQL}
<Editor
editorHeight={height}
label="Query"
mode="sql"
on:change={updateQuery}
readOnly={!editable}
value={query.fields.sql}
parameters={query.parameters}
/>
{:else if shouldDisplayJsonBox}
<Editor
editorHeight={height}
label="Query"
mode="json"
on:change={updateQuery}
readOnly={!editable}
value={query.fields.json}
parameters={query.parameters}
/>
{:else if schema.type === QueryTypes.FIELDS}
<FieldsBuilder bind:fields={query.fields} {schema} {editable} />
{#if schema.urlDisplay}
<div class="url-row">
<Label small>URL</Label>
<Input thin outline disabled value={urlDisplay} />
</div>
{/if}
{:else if query.fields.extra?.actionType === "pipeline"}
<br />
{#if !query.fields.steps?.length}
<div class="controls">
<Button
secondary
slot="buttons"
on:click={() => {
query.fields.steps = [
{
key: "$match",
value: "{\n\t\n}",
},
]
}}>Add stage</Button
>
</div>
<br />
{:else}
{#each query.fields.steps ?? [] as step, index}
<div class="block">
<div class="subblock">
<Divider noMargin />
<div class="blockSection">
<div class="block-options">
Stage {index + 1}
<div class="block-actions">
<div style="margin-right: 24px;">
{#if index > 0}
<ActionButton
quiet
on:click={() => {
updateEditorsOnSwap(index, index - 1)
const target = query.fields.steps[index - 1].key
query.fields.steps[index - 1].key =
query.fields.steps[index].key
query.fields.steps[index].key = target
}}
icon="ChevronUp"
/>
{/if}
{#if index < query.fields.steps.length - 1}
<ActionButton
quiet
on:click={() => {
updateEditorsOnSwap(index, index + 1)
const target = query.fields.steps[index + 1].key
query.fields.steps[index + 1].key =
query.fields.steps[index].key
query.fields.steps[index].key = target
}}
icon="ChevronDown"
/>
{/if}
</div>
<ActionButton
on:click={() => {
updateEditorsOnDelete(index)
query.fields.steps.splice(index, 1)
query.fields.steps = [...query.fields.steps]
}}
icon="DeleteOutline"
/>
</div>
</div>
<Layout noPadding gap="S">
<div class="fields">
<div class="block-field">
<Select
value={step.key}
options={schema.steps.map(s => s.key)}
on:change={({ detail }) => {
setEditorTemplate(step.key, detail, index)
}}
/>
<Editor
bind:this={stepEditors[index]}
editorHeight={height / 2}
mode="json"
value={typeof step.value === "string"
? step.value
: step.value.value}
on:change={({ detail }) => {
query.fields.steps[index].value = detail
}}
/>
</div>
</div>
</Layout>
</div>
</div>
<div class="separator" />
{#if index === query.fields.steps.length - 1}
<Icon
hoverable
name="AddCircle"
size="S"
on:click={() => {
query.fields.steps = [
...query.fields.steps,
{
key: "$match",
value: "{\n\t\n}",
},
]
}}
/>
<br />
{/if}
</div>
{/each}
{/if}
{/if}
{/key}
{/if}
<style>
.url-row {
display: grid;
grid-template-columns: 20% 1fr;
grid-gap: var(--spacing-l);
align-items: center;
}
.blockSection {
padding: var(--spacing-xl);
}
.block {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
margin-top: -6px;
}
.subblock {
width: 480px;
font-size: 16px;
background-color: var(--background);
border: 1px solid var(--spectrum-global-color-gray-300);
border-radius: 4px 4px 4px 4px;
}
.block-options {
justify-content: space-between;
display: flex;
align-items: center;
padding-bottom: 24px;
}
.block-actions {
justify-content: space-between;
display: flex;
align-items: right;
}
.fields {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
gap: var(--spacing-s);
}
.block-field {
display: grid;
grid-gap: 5px;
}
.separator {
width: 1px;
height: 25px;
border-left: 1px dashed var(--grey-4);
color: var(--grey-4);
/* center horizontally */
align-self: center;
}
.controls {
display: flex;
align-items: center;
justify-content: right;
}
</style>