Disabling save button when no changes made.
This commit is contained in:
parent
655c6034c2
commit
9aba344a45
|
@ -11,7 +11,7 @@
|
||||||
import { capitalise } from "helpers"
|
import { capitalise } from "helpers"
|
||||||
import { IntegrationTypes } from "constants"
|
import { IntegrationTypes } from "constants"
|
||||||
|
|
||||||
export let integration
|
export let datasource
|
||||||
export let schema
|
export let schema
|
||||||
export let creating
|
export let creating
|
||||||
|
|
||||||
|
@ -20,13 +20,13 @@
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return !(
|
return !(
|
||||||
(integration.source === IntegrationTypes.REST &&
|
(datasource.source === IntegrationTypes.REST &&
|
||||||
key === "defaultHeaders") ||
|
key === "defaultHeaders") ||
|
||||||
value.deprecated
|
value.deprecated
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
$: config = integration.config
|
$: config = datasource?.config
|
||||||
$: configKeys = Object.entries(schema || {})
|
$: configKeys = Object.entries(schema || {})
|
||||||
.filter(el => filter(el))
|
.filter(el => filter(el))
|
||||||
.map(([key]) => key)
|
.map(([key]) => key)
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
{#if !creating}
|
{#if !creating}
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<Label>{capitalise("Name")}</Label>
|
<Label>{capitalise("Name")}</Label>
|
||||||
<Input on:change bind:value={integration.name} />
|
<Input on:change bind:value={datasource.name} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#each configKeys as configKey}
|
{#each configKeys as configKey}
|
||||||
|
@ -54,6 +54,7 @@
|
||||||
bind:this={addButton}
|
bind:this={addButton}
|
||||||
defaults={schema[configKey].default}
|
defaults={schema[configKey].default}
|
||||||
bind:object={config[configKey]}
|
bind:object={config[configKey]}
|
||||||
|
on:change
|
||||||
noAddButton={true}
|
noAddButton={true}
|
||||||
/>
|
/>
|
||||||
{:else if schema[configKey].type === "boolean"}
|
{:else if schema[configKey].type === "boolean"}
|
||||||
|
|
|
@ -121,7 +121,6 @@
|
||||||
<div>
|
<div>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
size="S"
|
size="S"
|
||||||
quiet
|
|
||||||
icon="DataRefresh"
|
icon="DataRefresh"
|
||||||
on:click={updateDatasourceSchema}
|
on:click={updateDatasourceSchema}
|
||||||
>
|
>
|
||||||
|
@ -161,9 +160,7 @@
|
||||||
<Heading size="S">Relationships</Heading>
|
<Heading size="S">Relationships</Heading>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
icon="DataCorrelated"
|
icon="DataCorrelated"
|
||||||
primary
|
|
||||||
size="S"
|
size="S"
|
||||||
quiet
|
|
||||||
on:click={openRelationshipModal}
|
on:click={openRelationshipModal}
|
||||||
>
|
>
|
||||||
Define existing relationship
|
Define existing relationship
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { Divider, Heading, Button } from "@budibase/bbui"
|
import { Divider, Heading, ActionButton, Badge } from "@budibase/bbui"
|
||||||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
||||||
|
|
||||||
export let datasource
|
export let datasource
|
||||||
|
@ -9,13 +9,19 @@
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<div class="query-header">
|
<div class="query-header">
|
||||||
<Heading size="S">Headers</Heading>
|
<div class="badge">
|
||||||
<Button secondary on:click={() => addHeader.addEntry()}>Add Header</Button>
|
<Heading size="S">Headers</Heading>
|
||||||
|
<Badge quiet grey>Optional</Badge>
|
||||||
|
</div>
|
||||||
|
<ActionButton size="S" icon="Add" on:click={() => addHeader.addEntry()}
|
||||||
|
>Add Header</ActionButton
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<KeyValueBuilder
|
<KeyValueBuilder
|
||||||
bind:this={addHeader}
|
bind:this={addHeader}
|
||||||
bind:object={datasource.config.defaultHeaders}
|
bind:object={datasource.config.defaultHeaders}
|
||||||
noAddButton={true}
|
on:change
|
||||||
|
noAddButton
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -26,4 +32,9 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0 0 var(--spacing-s) 0;
|
margin: 0 0 var(--spacing-s) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
export let modal
|
export let modal
|
||||||
|
|
||||||
// kill the reference so the input isn't saved
|
// kill the reference so the input isn't saved
|
||||||
let config = cloneDeep(integration)
|
let datasource = cloneDeep(integration)
|
||||||
|
|
||||||
async function saveDatasource() {
|
async function saveDatasource() {
|
||||||
try {
|
try {
|
||||||
const resp = await save(config)
|
const resp = await save(datasource)
|
||||||
$goto(`./datasource/${resp._id}`)
|
$goto(`./datasource/${resp._id}`)
|
||||||
notifications.success(`Datasource updated successfully.`)
|
notifications.success(`Datasource updated successfully.`)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -24,10 +24,10 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title={`Connect to ${IntegrationNames[config.type]}`}
|
title={`Connect to ${IntegrationNames[datasource.type]}`}
|
||||||
onConfirm={() => saveDatasource()}
|
onConfirm={() => saveDatasource()}
|
||||||
onCancel={() => modal.show()}
|
onCancel={() => modal.show()}
|
||||||
confirmText={config.plus
|
confirmText={datasource.plus
|
||||||
? "Fetch tables from database"
|
? "Fetch tables from database"
|
||||||
: "Save and continue to query"}
|
: "Save and continue to query"}
|
||||||
cancelText="Back"
|
cancelText="Back"
|
||||||
|
@ -40,8 +40,8 @@
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<IntegrationConfigForm
|
<IntegrationConfigForm
|
||||||
schema={config.schema}
|
schema={datasource.schema}
|
||||||
integration={config}
|
bind:datasource
|
||||||
creating={true}
|
creating={true}
|
||||||
/>
|
/>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import { Icon, Button, Input } from "@budibase/bbui"
|
import { Icon, Button, Input } from "@budibase/bbui"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let defaults
|
export let defaults
|
||||||
export let object = defaults || {}
|
export let object = defaults || {}
|
||||||
|
@ -15,19 +18,25 @@
|
||||||
|
|
||||||
export function addEntry() {
|
export function addEntry() {
|
||||||
fields = [...fields, {}]
|
fields = [...fields, {}]
|
||||||
|
changed()
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteEntry(idx) {
|
function deleteEntry(idx) {
|
||||||
fields.splice(idx, 1)
|
fields.splice(idx, 1)
|
||||||
|
changed()
|
||||||
|
}
|
||||||
|
|
||||||
|
function changed() {
|
||||||
fields = fields
|
fields = fields
|
||||||
|
dispatch("change", fields)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Builds Objects with Key Value Pairs. Useful for building things like Request Headers. -->
|
<!-- Builds Objects with Key Value Pairs. Useful for building things like Request Headers. -->
|
||||||
<div class="container" class:readOnly>
|
<div class="container" class:readOnly>
|
||||||
{#each fields as field, idx}
|
{#each fields as field, idx}
|
||||||
<Input placeholder="Key" bind:value={field.name} />
|
<Input placeholder="Key" bind:value={field.name} on:change={changed} />
|
||||||
<Input placeholder="Value" bind:value={field.value} />
|
<Input placeholder="Value" bind:value={field.value} on:change={changed} />
|
||||||
{#if !readOnly}
|
{#if !readOnly}
|
||||||
<Icon hoverable name="Close" on:click={() => deleteEntry(idx)} />
|
<Icon hoverable name="Close" on:click={() => deleteEntry(idx)} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
Divider,
|
Divider,
|
||||||
Layout,
|
Layout,
|
||||||
notifications,
|
notifications,
|
||||||
|
ActionButton,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { datasources, integrations, queries, tables } from "stores/backend"
|
import { datasources, integrations, queries, tables } from "stores/backend"
|
||||||
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte"
|
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte"
|
||||||
|
@ -15,9 +16,28 @@
|
||||||
import ICONS from "components/backend/DatasourceNavigator/icons"
|
import ICONS from "components/backend/DatasourceNavigator/icons"
|
||||||
import { IntegrationTypes } from "constants"
|
import { IntegrationTypes } from "constants"
|
||||||
import { capitalise } from "helpers"
|
import { capitalise } from "helpers"
|
||||||
|
import { isEqual } from "lodash"
|
||||||
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
|
||||||
|
let baseDatasource, changed
|
||||||
|
|
||||||
$: datasource = $datasources.list.find(ds => ds._id === $datasources.selected)
|
$: datasource = $datasources.list.find(ds => ds._id === $datasources.selected)
|
||||||
$: integration = datasource && $integrations[datasource.source]
|
$: integration = datasource && $integrations[datasource.source]
|
||||||
|
$: {
|
||||||
|
if (
|
||||||
|
datasource &&
|
||||||
|
(!baseDatasource || baseDatasource.source !== datasource.source)
|
||||||
|
) {
|
||||||
|
baseDatasource = cloneDeep(datasource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$: hasChanged(baseDatasource, datasource)
|
||||||
|
|
||||||
|
function hasChanged(base, ds) {
|
||||||
|
if (base) {
|
||||||
|
changed = !isEqual(base, ds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function saveDatasource() {
|
async function saveDatasource() {
|
||||||
try {
|
try {
|
||||||
|
@ -28,6 +48,7 @@
|
||||||
}
|
}
|
||||||
await datasources.fetch()
|
await datasources.fetch()
|
||||||
notifications.success(`Datasource ${name} updated successfully.`)
|
notifications.success(`Datasource ${name} updated successfully.`)
|
||||||
|
baseDatasource = cloneDeep(datasource)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notifications.error(`Error saving datasource: ${err}`)
|
notifications.error(`Error saving datasource: ${err}`)
|
||||||
}
|
}
|
||||||
|
@ -49,7 +70,7 @@
|
||||||
height="26"
|
height="26"
|
||||||
width="26"
|
width="26"
|
||||||
/>
|
/>
|
||||||
<Heading size="M">{datasource.name}</Heading>
|
<Heading size="M">{baseDatasource.name}</Heading>
|
||||||
</header>
|
</header>
|
||||||
<Body size="M">{integration.description}</Body>
|
<Body size="M">{integration.description}</Body>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -57,14 +78,16 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="config-header">
|
<div class="config-header">
|
||||||
<Heading size="S">Configuration</Heading>
|
<Heading size="S">Configuration</Heading>
|
||||||
<Button secondary on:click={saveDatasource}>Save</Button>
|
<Button disabled={!changed} cta on:click={saveDatasource}>Save</Button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<Body size="S">
|
<Body size="S">
|
||||||
Connect your data source to Budibase using the config below.
|
Connect your data source to Budibase using the config below.
|
||||||
</Body>
|
</Body>
|
||||||
<IntegrationConfigForm
|
<IntegrationConfigForm
|
||||||
|
on:change={hasChanged}
|
||||||
schema={integration.datasource}
|
schema={integration.datasource}
|
||||||
integration={datasource}
|
bind:datasource
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if datasource.plus}
|
{#if datasource.plus}
|
||||||
|
@ -73,7 +96,9 @@
|
||||||
<Divider />
|
<Divider />
|
||||||
<div class="query-header">
|
<div class="query-header">
|
||||||
<Heading size="S">Queries</Heading>
|
<Heading size="S">Queries</Heading>
|
||||||
<Button secondary on:click={() => $goto("./new")}>Add Query</Button>
|
<ActionButton size="S" icon="Add" on:click={() => $goto("./new")}
|
||||||
|
>Add Query
|
||||||
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
<div class="query-list">
|
<div class="query-list">
|
||||||
{#each $queries.list.filter(query => query.datasourceId === datasource._id) as query}
|
{#each $queries.list.filter(query => query.datasourceId === datasource._id) as query}
|
||||||
|
@ -85,7 +110,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{#if datasource?.source === IntegrationTypes.REST}
|
{#if datasource?.source === IntegrationTypes.REST}
|
||||||
<RestExtraConfigForm bind:datasource />
|
<RestExtraConfigForm bind:datasource on:change={hasChanged} />
|
||||||
{/if}
|
{/if}
|
||||||
</Layout>
|
</Layout>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -153,7 +153,12 @@ module RestModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl(path: string, queryString: string): string {
|
getUrl(path: string, queryString: string): string {
|
||||||
return `${this.config.url}/${path}?${queryString}`
|
const main = `${path}?${queryString}`
|
||||||
|
if (!this.config.url) {
|
||||||
|
return main
|
||||||
|
} else {
|
||||||
|
return `${this.config.url}/${main}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async create({ path = "", queryString = "", headers = {}, json = {} }) {
|
async create({ path = "", queryString = "", headers = {}, json = {} }) {
|
||||||
|
|
Loading…
Reference in New Issue