Merge pull request #15744 from Budibase/BUDI-9127/fix-save-button-state

Fix save button state on rest
This commit is contained in:
Adria Navarro 2025-03-14 12:11:53 +01:00 committed by GitHub
commit 9d20f33a40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 67 additions and 62 deletions

View File

@ -9,6 +9,8 @@
export let type = "label"
export let size = "M"
export const disableEditingState = () => setEditing(false)
let editing = false
function setEditing(state) {

View File

@ -13,7 +13,7 @@
import { lowercase } from "@/helpers"
import DrawerBindableInput from "@/components/common/bindings/DrawerBindableInput.svelte"
let dispatch = createEventDispatcher()
const dispatch = createEventDispatcher()
export let defaults
export let object = defaults || {}
@ -47,10 +47,17 @@
}))
let fieldActivity = buildFieldActivity(activity)
$: object = fields.reduce(
(acc, next) => ({ ...acc, [next.name]: next.value }),
{}
)
$: fullObject = fields.reduce((acc, next) => {
acc[next.name] = next.value
return acc
}, {})
$: object = Object.entries(fullObject).reduce((acc, [key, next]) => {
if (key) {
acc[key] = next
}
return acc
}, {})
function buildFieldActivity(obj) {
if (!obj || typeof obj !== "object") {
@ -78,16 +85,19 @@
}
function changed() {
// Required for reactivity
fields = fields
const newActivity = {}
const trimmedFields = []
for (let idx = 0; idx < fields.length; idx++) {
const fieldName = fields[idx].name
if (fieldName) {
newActivity[fieldName] = fieldActivity[idx]
trimmedFields.push(fields[idx])
}
}
activity = newActivity
dispatch("change", fields)
dispatch("change", trimmedFields)
}
function isJsonArray(value) {
@ -102,7 +112,7 @@
</script>
<!-- Builds Objects with Key Value Pairs. Useful for building things like Request Headers. -->
{#if Object.keys(object || {}).length > 0}
{#if Object.keys(fullObject || {}).length > 0}
{#if headings}
<div class="container" class:container-active={toggle}>
<Label {tooltip}>{keyHeading || keyPlaceholder}</Label>

View File

@ -56,12 +56,13 @@
let query, datasource
let breakQs = {},
requestBindings = {}
let saveId, url
let saveId
let response, schema, enabledHeaders
let authConfigId
let dynamicVariables, addVariableModal, varBinding, globalDynamicBindings
let restBindings = getRestBindings()
let nestedSchemaFields = {}
let saving
let queryNameLabel
$: staticVariables = datasource?.config?.staticVariables || {}
@ -91,7 +92,7 @@
$: datasourceType = datasource?.source
$: integrationInfo = $integrations[datasourceType]
$: queryConfig = integrationInfo?.query
$: url = buildUrl(url, breakQs)
$: url = buildUrl(query?.fields?.path, breakQs)
$: checkQueryName(url)
$: responseSuccess = response?.info?.code >= 200 && response?.info?.code < 400
$: isGet = query?.queryVerb === "read"
@ -103,6 +104,10 @@
$: runtimeUrlQueries = readableToRuntimeMap(mergedBindings, breakQs)
$: originalQuery = originalQuery ?? cloneDeep(query)
$: builtQuery = buildQuery(query, runtimeUrlQueries, requestBindings)
$: isModified = JSON.stringify(originalQuery) !== JSON.stringify(builtQuery)
function getSelectedQuery() {
return cloneDeep(
$queries.list.find(q => q._id === queryId) || {
@ -126,7 +131,8 @@
?.trim() || inputUrl
function checkQueryName(inputUrl = null) {
if (query && (!query.name || query.flags.urlName)) {
if (query && (!query.name || query.flags?.urlName)) {
query.flags ??= {}
query.flags.urlName = true
query.name = cleanUrl(inputUrl)
}
@ -147,9 +153,12 @@
return qs.length === 0 ? newUrl : `${newUrl}?${qs}`
}
function buildQuery() {
const newQuery = cloneDeep(query)
const queryString = restUtils.buildQueryString(runtimeUrlQueries)
function buildQuery(fromQuery, urlQueries, requestBindings) {
if (!fromQuery) {
return
}
const newQuery = cloneDeep(fromQuery)
const queryString = restUtils.buildQueryString(urlQueries)
newQuery.parameters = restUtils.keyValueToQueryParameters(requestBindings)
newQuery.fields.requestBody =
@ -157,9 +166,8 @@
? readableToRuntimeMap(mergedBindings, newQuery.fields.requestBody)
: readableToRuntimeBinding(mergedBindings, newQuery.fields.requestBody)
newQuery.fields.path = url.split("?")[0]
newQuery.fields.path = url?.split("?")[0]
newQuery.fields.queryString = queryString
newQuery.fields.authConfigId = authConfigId
newQuery.fields.disabledHeaders = restUtils.flipHeaderState(enabledHeaders)
newQuery.schema = schema || {}
newQuery.nestedSchemaFields = nestedSchemaFields || {}
@ -168,13 +176,12 @@
}
async function saveQuery() {
const toSave = buildQuery()
const toSave = builtQuery
saving = true
try {
const isNew = !query._rev
const { _id } = await queries.save(toSave.datasourceId, toSave)
saveId = _id
query = getSelectedQuery()
notifications.success(`Request saved successfully`)
if (dynamicVariables) {
datasource.config.dynamicVariables = rebuildVariables(saveId)
datasource = await datasources.save({
@ -182,6 +189,13 @@
datasource,
})
}
notifications.success(`Request saved successfully`)
if (isNew) {
$goto(`../../${_id}`)
}
query = getSelectedQuery()
prettifyQueryRequestBody(
query,
requestBindings,
@ -189,11 +203,15 @@
staticVariables,
restBindings
)
if (isNew) {
$goto(`../../${_id}`)
}
// Force rebuilding original query
originalQuery = null
queryNameLabel.disableEditingState()
} catch (err) {
notifications.error(`Error saving query`)
} finally {
saving = false
}
}
@ -227,7 +245,7 @@
async function runQuery() {
try {
await validateQuery()
response = await queries.preview(buildQuery())
response = await queries.preview(builtQuery)
if (response.rows.length === 0) {
notifications.info("Request did not return any data")
} else {
@ -249,22 +267,6 @@
}
}
const getAuthConfigId = () => {
let id = query.fields.authConfigId
if (id) {
// find the matching config on the datasource
const matchedConfig = datasource?.config?.authConfigs?.filter(
c => c._id === id
)[0]
// clear the id if the config is not found (deleted)
// i.e. just show 'None' in the dropdown
if (!matchedConfig) {
id = undefined
}
}
return id
}
const buildAuthConfigs = datasource => {
if (datasource?.config?.authConfigs) {
return datasource.config.authConfigs.map(c => ({
@ -375,13 +377,6 @@
}
}
const paramsChanged = evt => {
breakQs = {}
for (let param of evt.detail) {
breakQs[param.name] = param.value
}
}
const urlChanged = evt => {
breakQs = {}
const qs = evt.target.value.split("?")[1]
@ -426,9 +421,7 @@
) {
query.fields.path = `${datasource.config.url}/${path ? path : ""}`
}
url = buildUrl(query.fields.path, breakQs)
requestBindings = restUtils.queryParametersToKeyValue(query.parameters)
authConfigId = getAuthConfigId()
if (!query.fields.disabledHeaders) {
query.fields.disabledHeaders = {}
}
@ -497,6 +490,7 @@
<Layout gap="S">
<div class="top-bar">
<EditableLabel
bind:this={queryNameLabel}
type="heading"
bind:value={query.name}
defaultValue="Untitled"
@ -504,7 +498,9 @@
on:save={saveQuery}
/>
<div class="controls">
<ConnectedQueryScreens sourceId={query._id} />
{#if query._id}
<ConnectedQueryScreens sourceId={query._id} />
{/if}
<div class="access">
<Label>Access</Label>
<AccessLevelSelect {query} {saveId} />
@ -524,13 +520,13 @@
<div class="url">
<Input
on:blur={urlChanged}
bind:value={url}
bind:value={query.fields.path}
placeholder="http://www.api.com/endpoint"
/>
</div>
<Button primary disabled={!url} on:click={runQuery}>Send</Button>
<Button
disabled={!query.name}
disabled={!query.name || !isModified || saving}
cta
on:click={saveQuery}
tooltip={!hasSchema
@ -557,16 +553,13 @@
/>
</Tab>
<Tab title="Params">
{#key breakQs}
<KeyValueBuilder
on:change={paramsChanged}
object={breakQs}
name="param"
headings
bindings={mergedBindings}
bindingDrawerLeft="260px"
/>
{/key}
<KeyValueBuilder
bind:object={breakQs}
name="param"
headings
bindings={mergedBindings}
bindingDrawerLeft="260px"
/>
</Tab>
<Tab title="Headers">
<KeyValueBuilder
@ -654,7 +647,7 @@
label="Auth"
labelPosition="left"
placeholder="None"
bind:value={authConfigId}
bind:value={query.fields.authConfigId}
options={authConfigs}
/>
</div>