From 755fa0ac4ae068d35d80a2b92d68254a985303bc Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 4 Jan 2021 18:57:16 +0000 Subject: [PATCH] allow execution of external connector queries from button clicks --- .../builder/src/builderStore/store/backend.js | 3 +- .../DataTable/ExternalDataSourceTable.svelte | 14 ++------ .../components/backend/DataTable/Table.svelte | 1 + .../buttons/CreateQueryButton.svelte | 8 ++--- .../DataTable/modals/CreateEditQuery.svelte | 2 ++ .../DatasourceNavigator.svelte | 28 --------------- .../TableNavigator/TableNavigator.svelte | 32 +---------------- .../EventsEditor/actions/CreateRow.svelte | 11 ------ .../EventsEditor/actions/DeleteRow.svelte | 2 -- .../EventsEditor/actions/ExecuteQuery.svelte | 32 +++++++++++++++++ .../EventsEditor/actions/index.js | 5 +++ .../pages/[application]/data/_layout.svelte | 36 +++++++++++++++++-- .../[selectedDatasource]/[query]/index.svelte | 4 +-- .../[selectedDatasource]/index.svelte | 2 +- packages/client/src/api/queries.js | 11 ++++++ packages/client/src/utils/buttonActions.js | 21 +++++++++-- .../server/src/api/controllers/datasource.js | 27 +++++++++++++- packages/server/src/api/routes/datasource.js | 5 +++ 18 files changed, 147 insertions(+), 97 deletions(-) create mode 100644 packages/builder/src/components/userInterface/EventsEditor/actions/ExecuteQuery.svelte diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 76888131a0..1d606901ec 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -1,7 +1,6 @@ import { writable, get } from "svelte/store" import { cloneDeep } from "lodash/fp" import api from "../api" -import { backendUiStore } from ".." const INITIAL_BACKEND_UI_STATE = { tables: [], @@ -63,6 +62,7 @@ export const getBackendUiStore = () => { select: async datasourceId => { store.update(state => { state.selectedDatasourceId = datasourceId + state.selectedQueryId = null return state }) }, @@ -123,6 +123,7 @@ export const getBackendUiStore = () => { queries: { select: queryId => store.update(state => { + state.selectedDatasourceId = null state.selectedQueryId = queryId return state }), diff --git a/packages/builder/src/components/backend/DataTable/ExternalDataSourceTable.svelte b/packages/builder/src/components/backend/DataTable/ExternalDataSourceTable.svelte index 75d2b8ffaa..85f23fe72b 100644 --- a/packages/builder/src/components/backend/DataTable/ExternalDataSourceTable.svelte +++ b/packages/builder/src/components/backend/DataTable/ExternalDataSourceTable.svelte @@ -6,21 +6,13 @@ import Table from "./Table.svelte" import CreateQueryButton from "components/backend/DataTable/buttons/CreateQueryButton.svelte" - export let datasourceId + export let datasource export let query = {} let data = [] let loading = false let error = false - $: datasourceId = $params.selectedDatasource - // TODO: refactor - // $: query = $backendUiStore.datasources.find( - // ds => ds._id === $params.selectedDatasource - // ).queries[$params.query] - $: title = query.name - $: schema = query.schema - async function fetchData() { try { loading = true @@ -46,8 +38,8 @@ {#if error}
{error}
{/if} - - +
+
diff --git a/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte b/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte index 6c67e44ae2..07246626eb 100644 --- a/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte +++ b/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte @@ -2,14 +2,11 @@ import { goto } from "@sveltech/routify" import { backendUiStore } from "builderStore" import { TableNames } from "constants" - import CreateTableModal from "./modals/CreateTableModal.svelte" import EditTablePopover from "./popovers/EditTablePopover.svelte" import EditViewPopover from "./popovers/EditViewPopover.svelte" - import { Modal, Switcher } from "@budibase/bbui" + import { Switcher } from "@budibase/bbui" import NavItem from "components/common/NavItem.svelte" - let modal - $: selectedView = $backendUiStore.selectedView && $backendUiStore.selectedView.name @@ -35,9 +32,6 @@ {#if $backendUiStore.selectedDatabase && $backendUiStore.selectedDatabase._id} -
- -
{#each $backendUiStore.tables as table, idx} {/if} - - - - - diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/CreateRow.svelte b/packages/builder/src/components/userInterface/EventsEditor/actions/CreateRow.svelte index 5ea1378d02..388b247a4b 100644 --- a/packages/builder/src/components/userInterface/EventsEditor/actions/CreateRow.svelte +++ b/packages/builder/src/components/userInterface/EventsEditor/actions/CreateRow.svelte @@ -13,9 +13,6 @@ tables: $backendUiStore.tables, }) - // just wraps binding in {{ ... }} - const toBindingExpression = bindingPath => `{{ ${bindingPath} }}` - const tableFields = tableId => { const table = $backendUiStore.tables.find(m => m._id === tableId) @@ -63,12 +60,4 @@ grid-column-start: 2; grid-column-end: 6; } - - .cannot-use { - color: var(--red); - font-size: var(--font-size-s); - text-align: center; - width: 70%; - margin: auto; - } diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/DeleteRow.svelte b/packages/builder/src/components/userInterface/EventsEditor/actions/DeleteRow.svelte index 230738bc95..b53b6f664a 100644 --- a/packages/builder/src/components/userInterface/EventsEditor/actions/DeleteRow.svelte +++ b/packages/builder/src/components/userInterface/EventsEditor/actions/DeleteRow.svelte @@ -42,8 +42,6 @@ typeof tableInfo === "string" ? tableInfo : tableInfo.tableId } } - - console.log(parameters) } } diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/ExecuteQuery.svelte b/packages/builder/src/components/userInterface/EventsEditor/actions/ExecuteQuery.svelte new file mode 100644 index 0000000000..95b92835e6 --- /dev/null +++ b/packages/builder/src/components/userInterface/EventsEditor/actions/ExecuteQuery.svelte @@ -0,0 +1,32 @@ + + +
+ + + + + + {#if parameters.datasourceId} + + + {/if} +
diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/index.js b/packages/builder/src/components/userInterface/EventsEditor/actions/index.js index 1c07356ee9..f9645b6caa 100644 --- a/packages/builder/src/components/userInterface/EventsEditor/actions/index.js +++ b/packages/builder/src/components/userInterface/EventsEditor/actions/index.js @@ -1,6 +1,7 @@ import NavigateTo from "./NavigateTo.svelte" import SaveRow from "./SaveRow.svelte" import DeleteRow from "./DeleteRow.svelte" +import ExecuteQuery from "./ExecuteQuery.svelte" // defines what actions are available, when adding a new one // the component is the setup panel for the action @@ -20,4 +21,8 @@ export default [ name: "Navigate To", component: NavigateTo, }, + { + name: "Execute Query", + component: ExecuteQuery, + }, ] diff --git a/packages/builder/src/pages/[application]/data/_layout.svelte b/packages/builder/src/pages/[application]/data/_layout.svelte index 2d1b254df7..ccf55ab602 100644 --- a/packages/builder/src/pages/[application]/data/_layout.svelte +++ b/packages/builder/src/pages/[application]/data/_layout.svelte @@ -1,7 +1,10 @@
@@ -40,6 +57,7 @@ grid-template-columns: 260px minmax(0, 1fr); background: var(--grey-2); } + .content { flex: 1 1 auto; padding: var(--spacing-l) 40px; @@ -50,6 +68,7 @@ align-items: stretch; gap: var(--spacing-l); } + .nav { overflow-y: auto; background: var(--background); @@ -59,5 +78,18 @@ justify-content: flex-start; align-items: stretch; gap: var(--spacing-l); + position: relative; + } + + i { + font-size: 20px; + position: absolute; + top: var(--spacing-l); + right: var(--spacing-xl); + } + + i:hover { + cursor: pointer; + color: var(--blue); } 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 67acdc46f3..32c53a0c2d 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 @@ -10,6 +10,6 @@ $: query = datasource && datasource.queries[$params.query] -{#if $backendUiStore.selectedDatabase._id && datasource} - +{#if $backendUiStore.selectedDatabase._id && datasource && query} + {/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 e7be79ebf7..c2f615c511 100644 --- a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte +++ b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte @@ -36,7 +36,7 @@ margin-bottom: var(--spacing-s); } section { - background: white; + background: var(--background); border-radius: var(--border-radius-m); padding: var(--spacing-xl); } diff --git a/packages/client/src/api/queries.js b/packages/client/src/api/queries.js index 42177be4cf..cfc92262a0 100644 --- a/packages/client/src/api/queries.js +++ b/packages/client/src/api/queries.js @@ -9,3 +9,14 @@ export const fetchQueryData = async ({ datasourceId, queryId }) => { }) return response.rows } + +/** + * Executes a query against an external data connector. + */ +export const executeQuery = async ({ datasourceId, queryId }) => { + const response = await API.post({ + url: `/api/datasources/${datasourceId}/queries/${queryId}`, + // body: params, + }) + return response.rows +} diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js index 2968525188..f17e5d0ee5 100644 --- a/packages/client/src/utils/buttonActions.js +++ b/packages/client/src/utils/buttonActions.js @@ -1,6 +1,6 @@ -import { enrichDataBinding } from "./enrichDataBinding" +import { enrichDataBinding, enrichDataBindings } from "./enrichDataBinding" import { routeStore } from "../store" -import { saveRow, deleteRow } from "../api" +import { saveRow, deleteRow, executeQuery } from "../api" const saveRowHandler = async (action, context) => { let draft = context[`${action.parameters.contextPath}_draft`] @@ -25,10 +25,27 @@ const navigationHandler = action => { routeStore.actions.navigate(action.parameters.url) } +const queryExecutionHandler = async (action, context) => { + const { datasourceId, queryId, params } = action.parameters + console.log(context) + // TODO: allow context based bindings for query params + // const enrichedQueryParameters = enrichDataBindings(params, context) + + // console.log({ + // action, + // context, + // // enrichedQueryParameters, + // datasourceId, + // // queryId + // }) + await executeQuery({ datasourceId, queryId }) +} + const handlerMap = { ["Save Row"]: saveRowHandler, ["Delete Row"]: deleteRowHandler, ["Navigate To"]: navigationHandler, + ["Execute Query"]: queryExecutionHandler, } /** diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 0b7ff1119b..d2a963d89a 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -115,7 +115,7 @@ exports.previewQuery = async function(ctx) { ctx.body = await new Integration(config, query).query() } -exports.executeQuery = async function(ctx) { +exports.fetchQuery = async function(ctx) { const db = new CouchDB(ctx.user.appId) const datasource = await db.get(ctx.params.datasourceId) @@ -139,3 +139,28 @@ exports.executeQuery = async function(ctx) { rows, } } + +exports.executeQuery = async function(ctx) { + const db = new CouchDB(ctx.user.appId) + + const datasource = await db.get(ctx.params.datasourceId) + + const query = datasource.queries[ctx.params.queryId] + + const Integration = integrations[datasource.source] + + if (!Integration) { + ctx.throw(400, "Integration type does not exist.") + return + } + + // TODO: allow the ability to POST parameters down when executing the query + // const customParams = ctx.request.body + + const response = await new Integration( + datasource.config, + query.queryString + ).query() + + ctx.body = response +} diff --git a/packages/server/src/api/routes/datasource.js b/packages/server/src/api/routes/datasource.js index b56d3bec84..19930e6f48 100644 --- a/packages/server/src/api/routes/datasource.js +++ b/packages/server/src/api/routes/datasource.js @@ -28,6 +28,11 @@ router datasourceController.previewQuery ) .get( + "/api/datasources/:datasourceId/queries/:queryId", + authorized(BUILDER), + datasourceController.fetchQuery + ) + .post( "/api/datasources/:datasourceId/queries/:queryId", authorized(BUILDER), datasourceController.executeQuery