Disabling save button when no changes made.

This commit is contained in:
mike12345567 2021-11-30 17:56:15 +00:00
parent 655c6034c2
commit 9aba344a45
7 changed files with 73 additions and 25 deletions

View File

@ -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"}

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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}

View File

@ -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>

View File

@ -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 = {} }) {