From 5787dd3f93d67a0e98d6df645a46aa5f6d69328a Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 15 Feb 2021 17:05:53 +0000 Subject: [PATCH 01/10] REST integration end to end --- .../integration/QueryFieldsBuilder.svelte | 79 +++++++++++++++++-- packages/server/src/api/controllers/query.js | 8 +- .../server/src/integrations/Integration.js | 1 + packages/server/src/integrations/index.js | 3 + packages/server/src/integrations/mysql.js | 10 +-- packages/server/src/integrations/rest.js | 57 +++++++++++++ 6 files changed, 144 insertions(+), 14 deletions(-) create mode 100644 packages/server/src/integrations/rest.js diff --git a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte index 79728f12fd..e7653f3c6b 100644 --- a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte +++ b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte @@ -18,21 +18,72 @@ $: fieldKeys = Object.keys(fields) $: schemaKeys = Object.keys(schema.fields) + $: console.log({ + fields, + schema + }) + function updateCustomFields({ detail }) { fields.customData = detail.value } + + function updateSubfieldName({ names, definition }) { + console.log(names, definition) + const temp = definition[names.old] + definition[names.new] = temp + delete definition[names.old] + // fields = fields + } + + // function addCustomField() { + + // } + + // function removeCustomField() { + + // }
{#each schemaKeys as field} - + + {#if schema.fields[field]?.type === "object"} + +
+ {#each Object.keys(fields[field] || {}) as subfield} + updateSubfieldName({ + names: { + new: e.target.value, + old: subfield + }, + definition: fields[field] + })} + /> + + { + delete fields[field][subfield] + fields[field] = fields[field] + }} /> + {/each} +
+ { + // set new empty field + fields[field] = { + ...fields[field] || {}, + [""]: "" + } + }} /> + {:else} + + {/if} {/each}
@@ -46,10 +97,22 @@ {/if} diff --git a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte index e7653f3c6b..3de8d317ad 100644 --- a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte +++ b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte @@ -8,6 +8,7 @@ Select, } from "@budibase/bbui" import Editor from "./QueryEditor.svelte" + import KeyValueBuilder from "./KeyValueBuilder.svelte" export let fields = {} export let schema @@ -27,53 +28,21 @@ fields.customData = detail.value } - function updateSubfieldName({ names, definition }) { - console.log(names, definition) - const temp = definition[names.old] - definition[names.new] = temp - delete definition[names.old] - // fields = fields - } - - // function addCustomField() { - - // } - - // function removeCustomField() { - - // }
{#each schemaKeys as field} - {#if schema.fields[field]?.type === "object"} -
- {#each Object.keys(fields[field] || {}) as subfield} - updateSubfieldName({ - names: { - new: e.target.value, - old: subfield - }, - definition: fields[field] - })} - /> - - { - delete fields[field][subfield] - fields[field] = fields[field] - }} /> - {/each} -
- { - // set new empty field - fields[field] = { - ...fields[field] || {}, - [""]: "" - } - }} /> + + {:else if schema.fields[field]?.type === "json"} + + fields[field] = detail.value} + readOnly={!editable} + value={fields[field]} /> {:else} - form { - width: 600px; - } - .field { margin-bottom: var(--spacing-m); display: grid; @@ -109,11 +74,4 @@ align-items: center; } - .inner-fields { - margin-bottom: var(--spacing-m); - display: grid; - grid-template-columns: 1fr 1fr 20px; - grid-gap: var(--spacing-m); - align-items: center; - } diff --git a/packages/builder/src/components/integration/QueryViewer.svelte b/packages/builder/src/components/integration/QueryViewer.svelte index 0f38f7650f..c53441941b 100644 --- a/packages/builder/src/components/integration/QueryViewer.svelte +++ b/packages/builder/src/components/integration/QueryViewer.svelte @@ -181,7 +181,13 @@ {#if data} {#if tab === 'JSON'} -
{JSON.stringify(data[0], undefined, 2)}
+
+              {#if !data[0]}
+                Please run your query to fetch some data.
+              {:else}
+                {JSON.stringify(data[0], undefined, 2)}
+              {/if}
+            
{:else if tab === 'PREVIEW'} {:else if tab === 'SCHEMA'} diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js index 7b063cb522..d5cec9c819 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.js @@ -53,6 +53,8 @@ router.use(async (ctx, next) => { router.get("/health", ctx => (ctx.status = 200)) +router.post("/yeet", ctx => (ctx.body = ctx.request.body)) + router.use(authRoutes.routes()) router.use(authRoutes.allowedMethods()) diff --git a/packages/server/src/integrations/Integration.js b/packages/server/src/integrations/Integration.js index 601a58d087..07d6d159b0 100644 --- a/packages/server/src/integrations/Integration.js +++ b/packages/server/src/integrations/Integration.js @@ -10,4 +10,5 @@ exports.FIELD_TYPES = { PASSWORD: "password", LIST: "list", OBJECT: "object", + JSON: "json", } diff --git a/packages/server/src/integrations/airtable.js b/packages/server/src/integrations/airtable.js index 088f642d51..2a581527a8 100644 --- a/packages/server/src/integrations/airtable.js +++ b/packages/server/src/integrations/airtable.js @@ -50,7 +50,7 @@ const SCHEMA = { }, }, delete: { - type: FIELD_TYPES.JSON, + type: QUERY_TYPES.JSON, }, }, } diff --git a/packages/server/src/integrations/rest.js b/packages/server/src/integrations/rest.js index 48ceb032c8..6b56303c51 100644 --- a/packages/server/src/integrations/rest.js +++ b/packages/server/src/integrations/rest.js @@ -11,6 +11,20 @@ const SCHEMA = { }, }, query: { + create: { + type: QUERY_TYPES.FIELDS, + fields: { + path: { + type: FIELD_TYPES.STRING, + }, + headers: { + type: FIELD_TYPES.OBJECT, + }, + requestBody: { + type: FIELD_TYPES.JSON, + }, + }, + }, read: { type: QUERY_TYPES.FIELDS, fields: { @@ -22,6 +36,34 @@ const SCHEMA = { }, }, }, + update: { + type: QUERY_TYPES.FIELDS, + fields: { + path: { + type: FIELD_TYPES.STRING, + }, + headers: { + type: FIELD_TYPES.OBJECT, + }, + requestBody: { + type: FIELD_TYPES.JSON, + }, + }, + }, + delete: { + type: QUERY_TYPES.FIELDS, + fields: { + path: { + type: FIELD_TYPES.STRING, + }, + headers: { + type: FIELD_TYPES.OBJECT, + }, + requestBody: { + type: FIELD_TYPES.JSON, + }, + }, + }, }, } @@ -30,9 +72,15 @@ class RestIntegration { this.config = config } - // create(query) { - // return this.query(query) - // } + async create({ path, headers = {}, requestBody }) { + const response = await fetch(this.config.url + path, { + method: "POST", + headers, + body: requestBody, + }) + + return await response.json() + } async read({ path, headers = {} }) { const response = await fetch(this.config.url + path, { @@ -42,13 +90,24 @@ class RestIntegration { return await response.json() } - // update(query) { - // return this.query(query) - // } + async update({ path, headers = {}, requestBody }) { + const response = await fetch(this.config.url + path, { + method: "POST", + headers, + body: requestBody, + }) - // delete(query) { - // return this.query(query) - // } + return await response.json() + } + + async delete({ path, headers = {} }) { + const response = await fetch(this.config.url + path, { + method: "DELETE", + headers, + }) + + return await response.json() + } } module.exports = { From 5d5637571ba0320e6a641d0f67a07892b617e4e6 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 15 Feb 2021 18:59:21 +0000 Subject: [PATCH 03/10] tidy up --- .../integration/KeyValueBuilder.svelte | 5 ++-- .../integration/QueryFieldsBuilder.svelte | 25 +++++++++---------- packages/server/src/api/index.js | 2 -- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/packages/builder/src/components/integration/KeyValueBuilder.svelte b/packages/builder/src/components/integration/KeyValueBuilder.svelte index 92a66f8813..7b4962edcb 100644 --- a/packages/builder/src/components/integration/KeyValueBuilder.svelte +++ b/packages/builder/src/components/integration/KeyValueBuilder.svelte @@ -23,8 +23,8 @@
{#each fields as field, idx} - - + + deleteEntry(idx)} /> {/each}
@@ -36,6 +36,7 @@ grid-template-columns: 1fr 1fr 20px; grid-gap: var(--spacing-m); align-items: center; + margin-bottom: var(--spacing-m); } .ri-close-circle-fill, diff --git a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte index 3de8d317ad..972bc2c373 100644 --- a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte +++ b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte @@ -19,11 +19,6 @@ $: fieldKeys = Object.keys(fields) $: schemaKeys = Object.keys(schema.fields) - $: console.log({ - fields, - schema - }) - function updateCustomFields({ detail }) { fields.customData = detail.value } @@ -34,15 +29,19 @@
{#each schemaKeys as field} {#if schema.fields[field]?.type === "object"} - - +
+ + +
{:else if schema.fields[field]?.type === "json"} - - fields[field] = detail.value} - readOnly={!editable} - value={fields[field]} /> +
+ + fields[field] = detail.value} + readOnly={!editable} + value={fields[field]} /> +
{:else} { router.get("/health", ctx => (ctx.status = 200)) -router.post("/yeet", ctx => (ctx.body = ctx.request.body)) - router.use(authRoutes.routes()) router.use(authRoutes.allowedMethods()) From 13c51f61d940ba978e09b723a0bcf6fd78dfe425 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 15 Feb 2021 19:57:49 +0000 Subject: [PATCH 04/10] ensure JSON parsed correctly --- packages/server/src/api/controllers/query.js | 10 ++++++++-- packages/server/src/integrations/rest.js | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/server/src/api/controllers/query.js b/packages/server/src/api/controllers/query.js index 71835ce8f6..04ff019a38 100644 --- a/packages/server/src/api/controllers/query.js +++ b/packages/server/src/api/controllers/query.js @@ -67,10 +67,16 @@ async function enrichQueryFields(fields, parameters) { } } - if (enrichedQuery.json || enrichedQuery.customData) { + if ( + enrichedQuery.json || + enrichedQuery.customData || + enrichedQuery.requestBody + ) { try { enrichedQuery.json = JSON.parse( - enrichedQuery.json || enrichedQuery.customData + enrichedQuery.json || + enrichedQuery.customData || + enrichedQuery.requestBody ) } catch (err) { throw { message: `JSON Invalid - error: ${err}` } diff --git a/packages/server/src/integrations/rest.js b/packages/server/src/integrations/rest.js index 6b56303c51..1496ae764b 100644 --- a/packages/server/src/integrations/rest.js +++ b/packages/server/src/integrations/rest.js @@ -72,11 +72,11 @@ class RestIntegration { this.config = config } - async create({ path, headers = {}, requestBody }) { + async create({ path, headers = {}, json }) { const response = await fetch(this.config.url + path, { method: "POST", headers, - body: requestBody, + body: JSON.stringify(json), }) return await response.json() @@ -90,11 +90,11 @@ class RestIntegration { return await response.json() } - async update({ path, headers = {}, requestBody }) { + async update({ path, headers = {}, json }) { const response = await fetch(this.config.url + path, { method: "POST", headers, - body: requestBody, + body: JSON.stringify(json), }) return await response.json() From 6e121b60458dde46919fd3803cb31f81b656e01d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 18 Feb 2021 16:58:10 +0000 Subject: [PATCH 05/10] design updates, changing query verb names to HTTP verbs --- .../popovers/ManageAccessPopover.svelte | 4 +- .../IntegrationConfigForm.svelte | 30 +++- .../TableIntegrationMenu/index.svelte | 22 ++- .../modals/CreateQueryModal.svelte | 61 -------- .../popovers/EditDatasourcePopover.svelte | 1 - .../popovers/EditQueryParamsPopover.svelte | 12 +- .../popovers/EditQueryPopover.svelte | 1 - .../integration/KeyValueBuilder.svelte | 2 +- .../integration/QueryFieldsBuilder.svelte | 33 +++-- .../integration/QueryParameterBuilder.svelte | 21 ++- .../components/integration/QueryViewer.svelte | 140 +++++++++--------- .../pages/[application]/data/_layout.svelte | 5 +- .../[selectedDatasource]/[query]/index.svelte | 2 + .../[selectedDatasource]/index.svelte | 37 +++-- packages/server/src/integrations/airtable.js | 1 + packages/server/src/integrations/arangodb.js | 1 + packages/server/src/integrations/couchdb.js | 1 + packages/server/src/integrations/dynamodb.js | 1 + .../server/src/integrations/elasticsearch.js | 1 + .../src/integrations/microsoftSqlServer.js | 1 + packages/server/src/integrations/mongodb.js | 3 + packages/server/src/integrations/mysql.js | 1 + packages/server/src/integrations/postgres.js | 1 + packages/server/src/integrations/rest.js | 30 +++- packages/server/src/integrations/s3.js | 1 + 25 files changed, 224 insertions(+), 189 deletions(-) delete mode 100644 packages/builder/src/components/backend/DatasourceNavigator/modals/CreateQueryModal.svelte diff --git a/packages/builder/src/components/backend/DataTable/popovers/ManageAccessPopover.svelte b/packages/builder/src/components/backend/DataTable/popovers/ManageAccessPopover.svelte index e8f6f6df0b..ee8162c8d4 100644 --- a/packages/builder/src/components/backend/DataTable/popovers/ManageAccessPopover.svelte +++ b/packages/builder/src/components/backend/DataTable/popovers/ManageAccessPopover.svelte @@ -30,7 +30,9 @@
Who Can Access This Data?
- +
diff --git a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte index f92224e39a..0239981a83 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte @@ -1,15 +1,33 @@ {#each Object.keys(integration) as configKey} - - +
+ {#if typeof integration[configKey] === 'object'} + + + {:else} + + + {/if} +
{/each} + + diff --git a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/index.svelte b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/index.svelte index dbe289caba..fe42a1dd9e 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/index.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/index.svelte @@ -2,7 +2,8 @@ import { onMount } from "svelte" import { backendUiStore } from "builderStore" import api from "builderStore/api" - import { Input, TextArea, Spacer } from "@budibase/bbui" + import { Input, Label, TextArea, Spacer } from "@budibase/bbui" + import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte" import ICONS from "../icons" export let integration = {} @@ -50,16 +51,21 @@ {/each}
- {#if schema} + +--> diff --git a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte b/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte index 92a541ac1d..dc07b31645 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte @@ -3,7 +3,6 @@ import { notifier } from "builderStore/store/notifications" import { DropdownMenu, Button, Input } from "@budibase/bbui" import ConfirmDialog from "components/common/ConfirmDialog.svelte" - import IntegrationConfigForm from "../TableIntegrationMenu//IntegrationConfigForm.svelte" import { DropdownContainer, DropdownItem } from "components/common/Dropdowns" export let query diff --git a/packages/builder/src/components/integration/KeyValueBuilder.svelte b/packages/builder/src/components/integration/KeyValueBuilder.svelte index 7b4962edcb..53f698e3f8 100644 --- a/packages/builder/src/components/integration/KeyValueBuilder.svelte +++ b/packages/builder/src/components/integration/KeyValueBuilder.svelte @@ -3,7 +3,7 @@ export let object = {} - let fields = [] + let fields = Object.entries(object).map(([name, value]) => ({ name, value })) $: object = fields.reduce( (acc, next) => ({ ...acc, [next.name]: next.value }), diff --git a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte index 972bc2c373..9168a01d11 100644 --- a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte +++ b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte @@ -22,35 +22,36 @@ function updateCustomFields({ detail }) { fields.customData = detail.value } -
{#each schemaKeys as field} - {#if schema.fields[field]?.type === "object"} + {#if schema.fields[field]?.type === 'object'}
- +
- {:else if schema.fields[field]?.type === "json"} + {:else if schema.fields[field]?.type === 'json'}
fields[field] = detail.value} + on:change={({ detail }) => (fields[field] = detail.value)} readOnly={!editable} value={fields[field]} />
{:else} - +
+ + +
{/if} {/each}
@@ -73,4 +74,10 @@ align-items: center; } + .horizontal { + display: grid; + grid-template-columns: 20% 1fr; + grid-gap: var(--spacing-l); + align-items: center; + } diff --git a/packages/builder/src/components/integration/QueryParameterBuilder.svelte b/packages/builder/src/components/integration/QueryParameterBuilder.svelte index d7eaa3bec1..8b9a3f2ba9 100644 --- a/packages/builder/src/components/integration/QueryParameterBuilder.svelte +++ b/packages/builder/src/components/integration/QueryParameterBuilder.svelte @@ -1,5 +1,5 @@
- Parameters +
+ Parameters + {#if !bindable} + + {/if} +
+ + Parameters come in two parts: the parameter name, and a default/fallback + value. +
{#each parameters as parameter, idx} @@ -59,9 +68,6 @@ {/if} {/each}
- {#if !bindable} - - {/if}
diff --git a/packages/builder/src/pages/[application]/data/_layout.svelte b/packages/builder/src/pages/[application]/data/_layout.svelte index ccf55ab602..84b3e2a29a 100644 --- a/packages/builder/src/pages/[application]/data/_layout.svelte +++ b/packages/builder/src/pages/[application]/data/_layout.svelte @@ -8,11 +8,11 @@ const tabs = [ { - title: "Tables", + title: "Internal", key: "table", }, { - title: "Data Sources", + title: "External", key: "datasource", }, ] @@ -67,6 +67,7 @@ justify-content: flex-start; align-items: stretch; gap: var(--spacing-l); + background: var(--background); } .nav { diff --git a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/[query]/index.svelte b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/[query]/index.svelte index c2419dd9a6..b7ea3b8218 100644 --- a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/[query]/index.svelte +++ b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/[query]/index.svelte @@ -36,6 +36,8 @@ diff --git a/packages/builder/src/components/integration/index.svelte b/packages/builder/src/components/integration/index.svelte index 0f87f61606..411eba3dda 100644 --- a/packages/builder/src/components/integration/index.svelte +++ b/packages/builder/src/components/integration/index.svelte @@ -8,13 +8,16 @@ const QueryTypes = { SQL: "sql", JSON: "json", - FIELDS: "fields", + FIELDS: "fields" } export let query + export let datasource export let schema export let editable = true + $: urlDisplay = schema.urlDisplay && `${datasource.config.url}${query.fields.path}${query.fields.queryString}` + function updateQuery({ detail }) { query.fields[schema.type] = detail.value } @@ -40,6 +43,27 @@ parameters={query.parameters} /> {:else if schema.type === QueryTypes.FIELDS} + {#if schema.urlDisplay} +
+ + +
+ {/if} {/if} {/key} {/if} + + diff --git a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte index 197baea112..274ce1f49e 100644 --- a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte +++ b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte @@ -50,6 +50,7 @@ +
diff --git a/packages/server/src/integrations/rest.js b/packages/server/src/integrations/rest.js index d90a0ce2a1..60f133d40b 100644 --- a/packages/server/src/integrations/rest.js +++ b/packages/server/src/integrations/rest.js @@ -20,10 +20,14 @@ const SCHEMA = { create: { displayName: "POST", type: QUERY_TYPES.FIELDS, + urlDisplay: true, fields: { path: { type: FIELD_TYPES.STRING, }, + queryString: { + type: FIELD_TYPES.STRING, + }, headers: { type: FIELD_TYPES.OBJECT, }, @@ -35,10 +39,14 @@ const SCHEMA = { read: { displayName: "GET", type: QUERY_TYPES.FIELDS, + urlDisplay: true, fields: { path: { type: FIELD_TYPES.STRING, }, + queryString: { + type: FIELD_TYPES.STRING, + }, headers: { type: FIELD_TYPES.OBJECT, }, @@ -47,10 +55,14 @@ const SCHEMA = { update: { displayName: "PUT", type: QUERY_TYPES.FIELDS, + urlDisplay: true, fields: { path: { type: FIELD_TYPES.STRING, }, + queryString: { + type: FIELD_TYPES.STRING, + }, headers: { type: FIELD_TYPES.OBJECT, }, @@ -62,10 +74,14 @@ const SCHEMA = { delete: { displayName: "DELETE", type: QUERY_TYPES.FIELDS, + urlDisplay: true, fields: { path: { type: FIELD_TYPES.STRING, }, + queryString: { + type: FIELD_TYPES.STRING, + }, headers: { type: FIELD_TYPES.OBJECT, }, @@ -82,8 +98,8 @@ class RestIntegration { this.config = config } - async create({ path, headers = {}, json }) { - const response = await fetch(this.config.url + path, { + async create({ path, queryString, headers = {}, json }) { + const response = await fetch(this.config.url + path + queryString, { method: "POST", headers: { ...this.config.defaultHeaders, @@ -95,8 +111,8 @@ class RestIntegration { return await response.json() } - async read({ path, headers = {} }) { - const response = await fetch(this.config.url + path, { + async read({ path, queryString, headers = {} }) { + const response = await fetch(this.config.url + path + queryString, { headers: { ...this.config.defaultHeaders, ...headers, @@ -106,8 +122,8 @@ class RestIntegration { return await response.json() } - async update({ path, headers = {}, json }) { - const response = await fetch(this.config.url + path, { + async update({ path, queryString, headers = {}, json }) { + const response = await fetch(this.config.url + path + queryString, { method: "POST", headers: { ...this.config.defaultHeaders, @@ -119,8 +135,8 @@ class RestIntegration { return await response.json() } - async delete({ path, headers = {} }) { - const response = await fetch(this.config.url + path, { + async delete({ path, queryString, headers = {} }) { + const response = await fetch(this.config.url + path + queryString, { method: "DELETE", headers: { ...this.config.defaultHeaders, From f53463ec0ccc777111c8421e6df013f9c68c9d75 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 18 Feb 2021 19:24:42 +0000 Subject: [PATCH 07/10] response parsing --- .../integration/KeyValueBuilder.svelte | 7 +-- .../integration/QueryFieldsBuilder.svelte | 4 ++ .../pages/[application]/data/_layout.svelte | 11 ++-- packages/server/src/integrations/rest.js | 59 ++++++++++++------- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/packages/builder/src/components/integration/KeyValueBuilder.svelte b/packages/builder/src/components/integration/KeyValueBuilder.svelte index 46bb73dad9..1d3fb5e8bb 100644 --- a/packages/builder/src/components/integration/KeyValueBuilder.svelte +++ b/packages/builder/src/components/integration/KeyValueBuilder.svelte @@ -1,5 +1,5 @@ -
+
{#each fields as field, idx} - deleteEntry(idx)} /> + {#if !readOnly} + deleteEntry(idx)} /> + {/if} {/each}
- +{#if !readOnly} + +{/if} diff --git a/packages/builder/src/pages/[application]/data/_layout.svelte b/packages/builder/src/pages/[application]/data/_layout.svelte index b0e1d17595..22c4751a40 100644 --- a/packages/builder/src/pages/[application]/data/_layout.svelte +++ b/packages/builder/src/pages/[application]/data/_layout.svelte @@ -27,9 +27,10 @@ {/each}
- - --> diff --git a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte index ee7fe5402e..fc861d7a92 100644 --- a/packages/builder/src/components/integration/QueryFieldsBuilder.svelte +++ b/packages/builder/src/components/integration/QueryFieldsBuilder.svelte @@ -6,7 +6,7 @@ Input, Heading, Select, - Spacer + Spacer, } from "@budibase/bbui" import Editor from "./QueryEditor.svelte" import KeyValueBuilder from "./KeyValueBuilder.svelte" diff --git a/packages/builder/src/components/integration/QueryParameterBuilder.svelte b/packages/builder/src/components/integration/QueryParameterBuilder.svelte index d456ee3a28..829aa00bb1 100644 --- a/packages/builder/src/components/integration/QueryParameterBuilder.svelte +++ b/packages/builder/src/components/integration/QueryParameterBuilder.svelte @@ -31,7 +31,7 @@
- Parameters + Parameters {#if !bindable} {/if} @@ -79,6 +79,7 @@ display: flex; align-items: center; justify-content: space-between; + height: 40px; } .parameters { diff --git a/packages/builder/src/components/integration/QueryViewer.svelte b/packages/builder/src/components/integration/QueryViewer.svelte index 3343390bbd..ad91b6baa0 100644 --- a/packages/builder/src/components/integration/QueryViewer.svelte +++ b/packages/builder/src/components/integration/QueryViewer.svelte @@ -131,10 +131,9 @@
- Query {integrationInfo.friendlyName} + Query {integrationInfo?.friendlyName}
- Config - + Config Provide a name for your query and select its function.
@@ -147,7 +146,9 @@
@@ -160,7 +161,8 @@ {#if shouldShowQueryConfig}
- Fields + Fields + Fill in the fields specific to this query.
- Query Results + Query Results
@@ -49,7 +66,9 @@ - +
From e08c91708016c294e0f725d9418a44231c2a18ce Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Fri, 19 Feb 2021 15:07:43 +0000 Subject: [PATCH 10/10] adding description blurbs to datasources --- .../components/integration/QueryViewer.svelte | 2 ++ .../datasource/[selectedDatasource]/index.svelte | 16 ++++++++++++---- packages/server/src/integrations/airtable.js | 2 ++ packages/server/src/integrations/arangodb.js | 2 ++ packages/server/src/integrations/couchdb.js | 2 ++ packages/server/src/integrations/dynamodb.js | 2 ++ .../server/src/integrations/elasticsearch.js | 2 ++ .../src/integrations/microsoftSqlServer.js | 2 ++ packages/server/src/integrations/mysql.js | 2 ++ packages/server/src/integrations/postgres.js | 2 ++ packages/server/src/integrations/rest.js | 2 ++ packages/server/src/integrations/s3.js | 2 ++ 12 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/components/integration/QueryViewer.svelte b/packages/builder/src/components/integration/QueryViewer.svelte index ad91b6baa0..0c3e687328 100644 --- a/packages/builder/src/components/integration/QueryViewer.svelte +++ b/packages/builder/src/components/integration/QueryViewer.svelte @@ -201,9 +201,11 @@ {#if !data[0]} + Please run your query to fetch some data. + {:else} {JSON.stringify(data[0], undefined, 2)} {/if} diff --git a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte index e97d005884..e6821e16fe 100644 --- a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte +++ b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte @@ -11,6 +11,7 @@ $: datasource = $backendUiStore.datasources.find( ds => ds._id === $backendUiStore.selectedDatasourceId ) + $: integration = datasource && $backendUiStore.integrations[datasource.source] async function saveDatasource() { // Create datasource @@ -38,7 +39,6 @@ ) return false } - return true }) @@ -55,12 +55,17 @@

{datasource.name}

- + + {integration.description} + +
+
Configuration
+ Connect your database to Budibase using the config below. @@ -73,8 +78,6 @@
- -
Queries @@ -97,11 +100,16 @@ h3 { margin: 0; } + section { margin: 0 auto; width: 800px; } + hr { + margin-bottom: var(--layout-m); + } + header { margin: 0 0 var(--spacing-xs) 0; display: flex; diff --git a/packages/server/src/integrations/airtable.js b/packages/server/src/integrations/airtable.js index cae394edff..004deff16e 100644 --- a/packages/server/src/integrations/airtable.js +++ b/packages/server/src/integrations/airtable.js @@ -3,6 +3,8 @@ const { FIELD_TYPES, QUERY_TYPES } = require("./Integration") const SCHEMA = { docs: "https://airtable.com/api", + description: + "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.", friendlyName: "Airtable", datasource: { apiKey: { diff --git a/packages/server/src/integrations/arangodb.js b/packages/server/src/integrations/arangodb.js index e14118e848..74d5390bff 100644 --- a/packages/server/src/integrations/arangodb.js +++ b/packages/server/src/integrations/arangodb.js @@ -4,6 +4,8 @@ const { FIELD_TYPES, QUERY_TYPES } = require("./Integration") const SCHEMA = { docs: "https://github.com/arangodb/arangojs", friendlyName: "ArangoDB", + description: + "ArangoDB is a scalable open-source multi-model database natively supporting graph, document and search. All supported data models & access patterns can be combined in queries allowing for maximal flexibility. ", datasource: { url: { type: FIELD_TYPES.STRING, diff --git a/packages/server/src/integrations/couchdb.js b/packages/server/src/integrations/couchdb.js index ab3cd8d437..df58b0e487 100644 --- a/packages/server/src/integrations/couchdb.js +++ b/packages/server/src/integrations/couchdb.js @@ -4,6 +4,8 @@ const { FIELD_TYPES, QUERY_TYPES } = require("./Integration") const SCHEMA = { docs: "https://docs.couchdb.org/en/stable/", friendlyName: "CouchDB", + description: + "Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.", datasource: { url: { type: FIELD_TYPES.STRING, diff --git a/packages/server/src/integrations/dynamodb.js b/packages/server/src/integrations/dynamodb.js index 36115f9166..668e11e263 100644 --- a/packages/server/src/integrations/dynamodb.js +++ b/packages/server/src/integrations/dynamodb.js @@ -3,6 +3,8 @@ const { FIELD_TYPES, QUERY_TYPES } = require("./Integration") const SCHEMA = { docs: "https://github.com/dabit3/dynamodb-documentclient-cheat-sheet", + description: + "Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.", friendlyName: "DynamoDB", datasource: { region: { diff --git a/packages/server/src/integrations/elasticsearch.js b/packages/server/src/integrations/elasticsearch.js index 23c4f6fe57..be1b945893 100644 --- a/packages/server/src/integrations/elasticsearch.js +++ b/packages/server/src/integrations/elasticsearch.js @@ -4,6 +4,8 @@ const { QUERY_TYPES, FIELD_TYPES } = require("./Integration") const SCHEMA = { docs: "https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html", + description: + "Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents.", friendlyName: "ElasticSearch", datasource: { url: { diff --git a/packages/server/src/integrations/microsoftSqlServer.js b/packages/server/src/integrations/microsoftSqlServer.js index 4f4da88cc3..eea67a7256 100644 --- a/packages/server/src/integrations/microsoftSqlServer.js +++ b/packages/server/src/integrations/microsoftSqlServer.js @@ -3,6 +3,8 @@ const { FIELD_TYPES } = require("./Integration") const SCHEMA = { docs: "https://github.com/tediousjs/node-mssql", + description: + "Microsoft SQL Server is a relational database management system developed by Microsoft. ", friendlyName: "MS SQL Server", datasource: { user: { diff --git a/packages/server/src/integrations/mysql.js b/packages/server/src/integrations/mysql.js index fe0f8e3f8b..48c0a4d704 100644 --- a/packages/server/src/integrations/mysql.js +++ b/packages/server/src/integrations/mysql.js @@ -4,6 +4,8 @@ const { FIELD_TYPES, QUERY_TYPES } = require("./Integration") const SCHEMA = { docs: "https://github.com/mysqljs/mysql", friendlyName: "MySQL", + description: + "MySQL Database Service is a fully managed database service to deploy cloud-native applications. ", datasource: { host: { type: FIELD_TYPES.STRING, diff --git a/packages/server/src/integrations/postgres.js b/packages/server/src/integrations/postgres.js index 4d13048ae6..c6a24577b3 100644 --- a/packages/server/src/integrations/postgres.js +++ b/packages/server/src/integrations/postgres.js @@ -3,6 +3,8 @@ const { Client } = require("pg") const SCHEMA = { docs: "https://node-postgres.com", friendlyName: "PostgreSQL", + description: + "PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.", datasource: { host: { type: "string", diff --git a/packages/server/src/integrations/rest.js b/packages/server/src/integrations/rest.js index 184b59149b..151cc22889 100644 --- a/packages/server/src/integrations/rest.js +++ b/packages/server/src/integrations/rest.js @@ -3,6 +3,8 @@ const { FIELD_TYPES, QUERY_TYPES } = require("./Integration") const SCHEMA = { docs: "https://github.com/node-fetch/node-fetch", + description: + "Representational state transfer (REST) is a de-facto standard for a software architecture for interactive applications that typically use multiple Web services. ", friendlyName: "REST API", datasource: { url: { diff --git a/packages/server/src/integrations/s3.js b/packages/server/src/integrations/s3.js index 5eb038819d..83d3508ee3 100644 --- a/packages/server/src/integrations/s3.js +++ b/packages/server/src/integrations/s3.js @@ -2,6 +2,8 @@ const AWS = require("aws-sdk") const SCHEMA = { docs: "https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html", + description: + "Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance.", friendlyName: "Amazon S3", datasource: { region: {