From 25d0f3f518af8c0d3eaab8e254b9cc59f7eea99f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 28 Jun 2023 11:59:53 +0100 Subject: [PATCH 1/4] Adding settings tab for SQL datasources. --- .../data/datasource/[datasourceId]/index.svelte | 7 +++++++ packages/server/src/integrations/utils.ts | 14 ++------------ packages/shared-core/src/helpers/integrations.ts | 15 ++++++++++++++- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte index 5b1715c46f..837cd7f675 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte @@ -10,6 +10,7 @@ import RestAuthenticationPanel from "./_components/panels/Authentication/index.svelte" import RestVariablesPanel from "./_components/panels/Variables/index.svelte" import PromptQueryModal from "./_components/PromptQueryModal.svelte" + import { helpers } from "@budibase/shared-core" let selectedPanel = null let panelOptions = [] @@ -39,6 +40,10 @@ panelOptions = ["Queries"] selectedPanel = "Queries" } + // always the last option for SQL + if (helpers.isSQL(datasource)) { + panelOptions.push("Settings") + } } @@ -82,6 +87,8 @@ {:else if selectedPanel === "Variables"} + {:else if selectedPanel === "Settings"} + Settings {:else} Something went wrong {/if} diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts index cc3caa6d5b..75deaf7f30 100644 --- a/packages/server/src/integrations/utils.ts +++ b/packages/server/src/integrations/utils.ts @@ -1,6 +1,7 @@ import { SourceName, SqlQuery, Datasource, Table } from "@budibase/types" import { DocumentType, SEPARATOR } from "../db/utils" import { FieldTypes, BuildSchemaErrors, InvalidColumns } from "../constants" +import { helpers } from "@budibase/shared-core" const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}` const ROW_ID_REGEX = /^\[.*]$/g @@ -178,18 +179,7 @@ export function getSqlQuery(query: SqlQuery | string): SqlQuery { } } -export function isSQL(datasource: Datasource): boolean { - if (!datasource || !datasource.source) { - return false - } - const SQL = [ - SourceName.POSTGRES, - SourceName.SQL_SERVER, - SourceName.MYSQL, - SourceName.ORACLE, - ] - return SQL.indexOf(datasource.source) !== -1 -} +export const isSQL = helpers.isSQL export function isIsoDateString(str: string) { if (!/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(str)) { diff --git a/packages/shared-core/src/helpers/integrations.ts b/packages/shared-core/src/helpers/integrations.ts index a7b74885d8..b8c220c6a5 100644 --- a/packages/shared-core/src/helpers/integrations.ts +++ b/packages/shared-core/src/helpers/integrations.ts @@ -1,5 +1,18 @@ -import { SourceName } from "@budibase/types" +import { Datasource, SourceName } from "@budibase/types" export function isGoogleSheets(type: SourceName) { return type === SourceName.GOOGLE_SHEETS } + +export function isSQL(datasource: Datasource): boolean { + if (!datasource || !datasource.source) { + return false + } + const SQL = [ + SourceName.POSTGRES, + SourceName.SQL_SERVER, + SourceName.MYSQL, + SourceName.ORACLE, + ] + return SQL.indexOf(datasource.source) !== -1 +} From d8fae3a3480829826af89a32c286df722e212362 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 28 Jun 2023 16:52:45 +0100 Subject: [PATCH 2/4] Adding SQL export functionality and settings tab for SQL databases. --- .../_components/panels/Settings.svelte | 38 +++++++++++++++++++ .../datasource/[datasourceId]/index.svelte | 3 +- packages/frontend-core/src/api/datasources.js | 6 +++ packages/frontend-core/src/utils/download.js | 13 +++++++ packages/frontend-core/src/utils/index.js | 1 + .../server/src/api/controllers/datasource.ts | 7 ++-- 6 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Settings.svelte create mode 100644 packages/frontend-core/src/utils/download.js diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Settings.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Settings.svelte new file mode 100644 index 0000000000..894b705a30 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Settings.svelte @@ -0,0 +1,38 @@ + + + +
+ + Troubleshooting + Download your schema to share with the Budibase team +
+ +
+
+
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte index 837cd7f675..0a7f5ef134 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte @@ -10,6 +10,7 @@ import RestAuthenticationPanel from "./_components/panels/Authentication/index.svelte" import RestVariablesPanel from "./_components/panels/Variables/index.svelte" import PromptQueryModal from "./_components/PromptQueryModal.svelte" + import SettingsPanel from "./_components/panels/Settings.svelte" import { helpers } from "@budibase/shared-core" let selectedPanel = null @@ -88,7 +89,7 @@ {:else if selectedPanel === "Variables"} {:else if selectedPanel === "Settings"} - Settings + {:else} Something went wrong {/if} diff --git a/packages/frontend-core/src/api/datasources.js b/packages/frontend-core/src/api/datasources.js index 1ba17cc610..7cc05960d7 100644 --- a/packages/frontend-core/src/api/datasources.js +++ b/packages/frontend-core/src/api/datasources.js @@ -83,4 +83,10 @@ export const buildDatasourceEndpoints = API => ({ body: { datasource }, }) }, + + fetchExternalSchema: async datasourceId => { + return await API.get({ + url: `/api/datasources/${datasourceId}/schema/external`, + }) + }, }) diff --git a/packages/frontend-core/src/utils/download.js b/packages/frontend-core/src/utils/download.js new file mode 100644 index 0000000000..681bc8648e --- /dev/null +++ b/packages/frontend-core/src/utils/download.js @@ -0,0 +1,13 @@ +export function downloadText(filename, text) { + if (typeof text === "object") { + text = JSON.stringify(text) + } + const blob = new Blob([text], { type: "plain/text" }) + const url = URL.createObjectURL(blob) + const link = document.createElement("a") + link.href = url + link.download = filename + link.click() + + URL.revokeObjectURL(url) +} diff --git a/packages/frontend-core/src/utils/index.js b/packages/frontend-core/src/utils/index.js index 26e44410ba..dd04dd6c28 100644 --- a/packages/frontend-core/src/utils/index.js +++ b/packages/frontend-core/src/utils/index.js @@ -5,3 +5,4 @@ export * as RoleUtils from "./roles" export * as Utils from "./utils" export { memo, derivedMemo } from "./memo" export { createWebsocket } from "./websocket" +export { downloadText } from "./download" diff --git a/packages/server/src/api/controllers/datasource.ts b/packages/server/src/api/controllers/datasource.ts index 86669845e6..92b5844869 100644 --- a/packages/server/src/api/controllers/datasource.ts +++ b/packages/server/src/api/controllers/datasource.ts @@ -427,8 +427,8 @@ export async function destroy(ctx: UserCtx) { } export async function find(ctx: UserCtx) { - const database = context.getAppDB() - const datasource = await database.get(ctx.params.datasourceId) + const db = context.getAppDB() + const datasource = await db.get(ctx.params.datasourceId) ctx.body = await sdk.datasources.removeSecretSingle(datasource) } @@ -443,7 +443,8 @@ export async function query(ctx: UserCtx) { } export async function getExternalSchema(ctx: UserCtx) { - const { datasource } = ctx.request.body + const db = context.getAppDB() + const datasource = await db.get(ctx.params.datasourceId) const enrichedDatasource = await getAndMergeDatasource(datasource) const connector = await getConnector(enrichedDatasource) From 81c8bee81ea6b56abd653ef0b7766f9d88d57885 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 28 Jun 2023 17:17:24 +0100 Subject: [PATCH 3/4] Quick fix to stop custom role names from being updated. --- .../backend/DataTable/modals/EditRoles.svelte | 7 +++--- packages/server/src/api/controllers/role.ts | 25 +++++++++++-------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte b/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte index b638d23168..949edc5ee1 100644 --- a/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte @@ -84,7 +84,7 @@ await roles.save(selectedRole) notifications.success("Role saved successfully") } catch (error) { - notifications.error("Error saving role") + notifications.error(`Error deleting role - ${error.message}`) return false } } @@ -96,7 +96,8 @@ changeRole() notifications.success("Role deleted successfully") } catch (error) { - notifications.error("Error deleting role") + notifications.error(`Error deleting role - ${error.message}`) + return false } } @@ -139,7 +140,7 @@