From 4faa7c93387bf3805b9b6cbdf228947e620c9666 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 18 Jan 2022 13:19:41 +0000 Subject: [PATCH 01/21] Derive safe array-like value as the default value for multi-select fields --- .../components/app/forms/MultiFieldSelect.svelte | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/client/src/components/app/forms/MultiFieldSelect.svelte b/packages/client/src/components/app/forms/MultiFieldSelect.svelte index cecc569b6f..d09a8730ae 100644 --- a/packages/client/src/components/app/forms/MultiFieldSelect.svelte +++ b/packages/client/src/components/app/forms/MultiFieldSelect.svelte @@ -19,6 +19,7 @@ let fieldApi let fieldSchema + $: safeDefaultValue = getSafeDefaultValue(defaultValue) $: flatOptions = optionsSource == null || optionsSource === "schema" $: options = getOptions( optionsSource, @@ -28,6 +29,16 @@ valueColumn, customOptions ) + + const getSafeDefaultValue = value => { + if (value == null || value === "") { + return [] + } + if (!Array.isArray(value)) { + return [value] + } + return value + } Date: Tue, 18 Jan 2022 13:20:06 +0000 Subject: [PATCH 02/21] Transform the output of JS expressions to be actual types rather than strings --- .../src/helpers/javascript.js | 6 ++- .../src/processors/postprocessor.js | 5 ++ .../string-templates/test/javascript.spec.js | 48 ++++++++++++++++++- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/packages/string-templates/src/helpers/javascript.js b/packages/string-templates/src/helpers/javascript.js index 9231283e89..0173be0b54 100644 --- a/packages/string-templates/src/helpers/javascript.js +++ b/packages/string-templates/src/helpers/javascript.js @@ -1,5 +1,6 @@ const { atob } = require("../utilities") const { cloneDeep } = require("lodash/fp") +const { LITERAL_MARKER } = require("../helpers/constants") // The method of executing JS scripts depends on the bundle being built. // This setter is used in the entrypoint (either index.cjs or index.mjs). @@ -46,8 +47,9 @@ module.exports.processJS = (handlebars, context) => { $: path => getContextValue(path, cloneDeep(context)), } - // Create a sandbox with out context and run the JS - return runJS(js, sandboxContext) + // Create a sandbox with our context and run the JS + const res = { data: runJS(js, sandboxContext) } + return `{{${LITERAL_MARKER} js_result-${JSON.stringify(res)}}}` } catch (error) { return "Error while executing JS" } diff --git a/packages/string-templates/src/processors/postprocessor.js b/packages/string-templates/src/processors/postprocessor.js index 4d1c84013a..7fc3f663fe 100644 --- a/packages/string-templates/src/processors/postprocessor.js +++ b/packages/string-templates/src/processors/postprocessor.js @@ -36,6 +36,11 @@ module.exports.processors = [ return value === "true" case "object": return JSON.parse(value) + case "js_result": + // We use the literal helper to process the result of JS expressions + // as we want to be able to return any types. + // We wrap the value in an abject to be able to use undefined properly. + return JSON.parse(value).data } return value }), diff --git a/packages/string-templates/test/javascript.spec.js b/packages/string-templates/test/javascript.spec.js index 05cc80331a..5363f37e02 100644 --- a/packages/string-templates/test/javascript.spec.js +++ b/packages/string-templates/test/javascript.spec.js @@ -7,7 +7,7 @@ const processJS = (js, context) => { describe("Test the JavaScript helper", () => { it("should execute a simple expression", () => { const output = processJS(`return 1 + 2`) - expect(output).toBe("3") + expect(output).toBe(3) }) it("should be able to use primitive bindings", () => { @@ -50,6 +50,52 @@ describe("Test the JavaScript helper", () => { expect(output).toBe("shazbat") }) + it("should be able to return an object", () => { + const output = processJS(`return $("foo")`, { + foo: { + bar: { + baz: "shazbat", + }, + }, + }) + expect(output.bar.baz).toBe("shazbat") + }) + + it("should be able to return an array", () => { + const output = processJS(`return $("foo")`, { + foo: ["a", "b", "c"], + }) + expect(output[2]).toBe("c") + }) + + it("should be able to return null", () => { + const output = processJS(`return $("foo")`, { + foo: null, + }) + expect(output).toBe(null) + }) + + it("should be able to return undefined", () => { + const output = processJS(`return $("foo")`, { + foo: undefined, + }) + expect(output).toBe(undefined) + }) + + it("should be able to return 0", () => { + const output = processJS(`return $("foo")`, { + foo: 0, + }) + expect(output).toBe(0) + }) + + it("should be able to return an empty string", () => { + const output = processJS(`return $("foo")`, { + foo: "", + }) + expect(output).toBe("") + }) + it("should be able to use a deep array binding", () => { const output = processJS(`return $("foo.0.bar")`, { foo: [ From 89bb1fcdaa7d94a217f852c6052de0271dfe8dd9 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 18 Jan 2022 13:20:28 +0000 Subject: [PATCH 03/21] Fix issue with array field validation --- .../server/src/api/controllers/row/utils.js | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/server/src/api/controllers/row/utils.js b/packages/server/src/api/controllers/row/utils.js index 71b22375f7..e18aee582f 100644 --- a/packages/server/src/api/controllers/row/utils.js +++ b/packages/server/src/api/controllers/row/utils.js @@ -52,21 +52,29 @@ exports.validate = async ({ appId, tableId, row, table }) => { const constraints = cloneDeep(table.schema[fieldName].constraints) const type = table.schema[fieldName].type // special case for options, need to always allow unselected (null) - if ( - (type === FieldTypes.OPTIONS || type === FieldTypes.ARRAY) && - constraints.inclusion - ) { + if (type === FieldTypes.OPTIONS && constraints.inclusion) { constraints.inclusion.push(null) } let res // Validate.js doesn't seem to handle array - if (type === FieldTypes.ARRAY && row[fieldName] && row[fieldName].length) { - row[fieldName].map(val => { - if (!constraints.inclusion.includes(val)) { - errors[fieldName] = "Field not in list" - } - }) + if (type === FieldTypes.ARRAY) { + const hasValues = + Array.isArray(row[fieldName]) && row[fieldName].length > 0 + + // Check values are valid if values are specified + if (hasValues) { + row[fieldName].map(val => { + if (!constraints.inclusion.includes(val)) { + errors[fieldName] = "Value not in list" + } + }) + } + + // Check for required constraint + if (constraints.presence === true && !hasValues) { + errors[fieldName] = "Required field" + } } else if (type === FieldTypes.JSON && typeof row[fieldName] === "string") { // this should only happen if there is an error try { From 117cdcbd02506bd4bba9a22940ada4786333569c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 18 Jan 2022 15:25:43 +0000 Subject: [PATCH 04/21] Revert changes to MultiFieldSelect --- .../components/app/forms/MultiFieldSelect.svelte | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/client/src/components/app/forms/MultiFieldSelect.svelte b/packages/client/src/components/app/forms/MultiFieldSelect.svelte index d09a8730ae..cecc569b6f 100644 --- a/packages/client/src/components/app/forms/MultiFieldSelect.svelte +++ b/packages/client/src/components/app/forms/MultiFieldSelect.svelte @@ -19,7 +19,6 @@ let fieldApi let fieldSchema - $: safeDefaultValue = getSafeDefaultValue(defaultValue) $: flatOptions = optionsSource == null || optionsSource === "schema" $: options = getOptions( optionsSource, @@ -29,16 +28,6 @@ valueColumn, customOptions ) - - const getSafeDefaultValue = value => { - if (value == null || value === "") { - return [] - } - if (!Array.isArray(value)) { - return [value] - } - return value - } Date: Tue, 18 Jan 2022 15:34:10 +0000 Subject: [PATCH 05/21] Fix data fetch for nested providers, JSON arrays or array fields not working --- packages/client/src/utils/fetch/DataFetch.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/client/src/utils/fetch/DataFetch.js b/packages/client/src/utils/fetch/DataFetch.js index 884e12feb1..7fe53bb8af 100644 --- a/packages/client/src/utils/fetch/DataFetch.js +++ b/packages/client/src/utils/fetch/DataFetch.js @@ -110,12 +110,6 @@ export default class DataFetch { */ async getInitialData() { const { datasource, filter, sortColumn, paginate } = this.options - const tableId = datasource?.tableId - - // Ensure table ID exists - if (!tableId) { - return - } // Fetch datasource definition and determine feature flags const definition = await this.constructor.getDefinition(datasource) From 9b885d0207fa859a109f404b253fdb3056959433 Mon Sep 17 00:00:00 2001 From: Michael Drury Date: Tue, 18 Jan 2022 20:54:19 +0000 Subject: [PATCH 06/21] Quick fix for #4093 - make sure the App ID/App URL returned for deployed apps is always lowercase, as URLs are not case sensitive and should not be compared as such. --- packages/server/src/utilities/workerRequests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/utilities/workerRequests.js b/packages/server/src/utilities/workerRequests.js index 92dffc8d3f..421b8c426e 100644 --- a/packages/server/src/utilities/workerRequests.js +++ b/packages/server/src/utilities/workerRequests.js @@ -71,7 +71,7 @@ exports.getDeployedApps = async () => { for (let [key, value] of Object.entries(json)) { if (value.url) { value.url = value.url.toLowerCase() - apps[key] = value + apps[key.toLowerCase()] = value } } return apps From 2eb6bef9f5255148c820c0b3b5d8d92db7c86a50 Mon Sep 17 00:00:00 2001 From: Budibase Release Bot <> Date: Wed, 19 Jan 2022 10:13:22 +0000 Subject: [PATCH 07/21] v1.0.44 --- lerna.json | 2 +- packages/backend-core/package.json | 2 +- packages/bbui/package.json | 2 +- packages/builder/package.json | 8 ++++---- packages/cli/package.json | 2 +- packages/client/package.json | 6 +++--- packages/server/package.json | 8 ++++---- packages/string-templates/package.json | 2 +- packages/worker/package.json | 6 +++--- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lerna.json b/lerna.json index 42925e163b..ad778bd2cf 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.43", + "version": "1.0.44", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index ac5288687d..be37988678 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.0.43", + "version": "1.0.44", "description": "Budibase backend core libraries used in server and worker", "main": "src/index.js", "author": "Budibase", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index af9e518b7b..6d71fd3fbc 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "1.0.43", + "version": "1.0.44", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/builder/package.json b/packages/builder/package.json index 189497dd73..c392fe39b8 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "1.0.43", + "version": "1.0.44", "license": "GPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^1.0.43", - "@budibase/client": "^1.0.43", + "@budibase/bbui": "^1.0.44", + "@budibase/client": "^1.0.44", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^1.0.43", + "@budibase/string-templates": "^1.0.44", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index 5f3f2786bd..0af381d319 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "1.0.43", + "version": "1.0.44", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { diff --git a/packages/client/package.json b/packages/client/package.json index aeafd8d1c3..f0639d8bb4 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "1.0.43", + "version": "1.0.44", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,9 +19,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^1.0.43", + "@budibase/bbui": "^1.0.44", "@budibase/standard-components": "^0.9.139", - "@budibase/string-templates": "^1.0.43", + "@budibase/string-templates": "^1.0.44", "regexparam": "^1.3.0", "shortid": "^2.2.15", "svelte-spa-router": "^3.0.5" diff --git a/packages/server/package.json b/packages/server/package.json index 70904e148f..6f721f84d8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "1.0.43", + "version": "1.0.44", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -70,9 +70,9 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "^10.0.3", - "@budibase/backend-core": "^1.0.43", - "@budibase/client": "^1.0.43", - "@budibase/string-templates": "^1.0.43", + "@budibase/backend-core": "^1.0.44", + "@budibase/client": "^1.0.44", + "@budibase/string-templates": "^1.0.44", "@bull-board/api": "^3.7.0", "@bull-board/koa": "^3.7.0", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index e0bcd641c8..2a7d9d95bf 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "1.0.43", + "version": "1.0.44", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/worker/package.json b/packages/worker/package.json index 9c2238501d..78f9b1544b 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "1.0.43", + "version": "1.0.44", "description": "Budibase background service", "main": "src/index.js", "repository": { @@ -29,8 +29,8 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "^1.0.43", - "@budibase/string-templates": "^1.0.43", + "@budibase/backend-core": "^1.0.44", + "@budibase/string-templates": "^1.0.44", "@koa/router": "^8.0.0", "@sentry/node": "^6.0.0", "@techpass/passport-openidconnect": "^0.3.0", From 3c1414dc180e7185c0e1742069dc75f6b8841855 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 19 Jan 2022 15:22:55 +0000 Subject: [PATCH 08/21] fix issue with templates showing over more than two rows --- packages/builder/src/pages/builder/portal/apps/index.svelte | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index ac10b5317f..4df434ecdd 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -474,9 +474,12 @@ } .grid { + height: 200px; display: grid; + overflow: hidden; grid-gap: var(--spacing-xl); grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); + grid-template-rows: minmax(100px, 1fr) minmax(100px, 1fr) minmax(0px, 0); } .template-card { height: 80px; From 7ab4d5f3d3ed12b92882c83a880bdded9a309dfc Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 19 Jan 2022 18:29:09 +0000 Subject: [PATCH 09/21] remove uneeded app creation modal --- .../components/start/CreateAppModal.svelte | 83 +++++++------------ .../src/components/start/TemplateList.svelte | 69 --------------- .../pages/builder/portal/apps/index.svelte | 11 ++- 3 files changed, 38 insertions(+), 125 deletions(-) delete mode 100644 packages/builder/src/components/start/TemplateList.svelte diff --git a/packages/builder/src/components/start/CreateAppModal.svelte b/packages/builder/src/components/start/CreateAppModal.svelte index 178588f608..60065b6eef 100644 --- a/packages/builder/src/components/start/CreateAppModal.svelte +++ b/packages/builder/src/components/start/CreateAppModal.svelte @@ -11,7 +11,6 @@ import { capitalise } from "helpers" import { goto } from "@roxi/routify" import { APP_NAME_REGEX } from "constants" - import TemplateList from "./TemplateList.svelte" export let template export let inline @@ -147,58 +146,34 @@ } -{#if showTemplateSelection} - { - template = {} - return false - }} - showCancelButton={!inline} - showCloseIcon={!inline} - > - { - if (!selected) { - template = useImport ? { fromFile: true } : {} - return - } - template = selected + + {#if template?.fromFile} + { + $values.file = e.detail?.[0] + $touched.file = true }} /> - -{:else} - - {#if template?.fromFile} - { - $values.file = e.detail?.[0] - $touched.file = true - }} - /> - {/if} - ($touched.name = true)} - label="Name" - placeholder={$auth.user.firstName - ? `${$auth.user.firstName}'s app` - : "My app"} - /> - -{/if} + {/if} + ($touched.name = true)} + label="Name" + placeholder={$auth.user.firstName + ? `${$auth.user.firstName}'s app` + : "My app"} + /> + diff --git a/packages/builder/src/components/start/TemplateList.svelte b/packages/builder/src/components/start/TemplateList.svelte deleted file mode 100644 index 90573bddff..0000000000 --- a/packages/builder/src/components/start/TemplateList.svelte +++ /dev/null @@ -1,69 +0,0 @@ - - - -
onSelect(null)}> -
- -
- Start from scratch -

BLANK

-
-
onSelect(null, { useImport: true })} - > -
- -
- Import an app -

BLANK

-
-
- - diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index 4df434ecdd..31530c5ef9 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -78,6 +78,7 @@ } const initiateAppCreation = () => { + template = {} creationModal.show() creatingApp = true } @@ -304,10 +305,16 @@ Export apps {/if} - - From ee20f2a934501bb556dc9ccf9abd17e1c23bedc5 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 19 Jan 2022 19:40:28 +0000 Subject: [PATCH 10/21] add splash screen for apps page --- .../pages/builder/portal/apps/index.svelte | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index 31530c5ef9..e7b2724de0 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -11,6 +11,7 @@ notifications, Body, Search, + Icon, } from "@budibase/bbui" import Spinner from "components/common/Spinner.svelte" import CreateAppModal from "components/start/CreateAppModal.svelte" @@ -27,6 +28,7 @@ import AppRow from "components/start/AppRow.svelte" import { AppStatus } from "constants" import analytics, { Events } from "analytics" + import Logo from "assets/bb-space-man.svg" let sortBy = "name" let template @@ -394,11 +396,26 @@ {/if} - {#if !enrichedApps.length && !creatingApp && loaded} + {#if !enrichedApps.length}
- - - +
+
+ + logo +
+ LET’S GET STARTED! +
+ +
+
+
{/if} @@ -486,10 +503,10 @@ overflow: hidden; grid-gap: var(--spacing-xl); grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); - grid-template-rows: minmax(100px, 1fr) minmax(100px, 1fr) minmax(0px, 0); + grid-template-rows: minmax(70px, 1fr) minmax(100px, 1fr) minmax(0px, 0); } .template-card { - height: 80px; + height: 70px; border-radius: var(--border-radius-s); border: 1px solid var(--spectrum-global-color-gray-300); cursor: pointer; @@ -543,4 +560,42 @@ justify-content: center; align-items: center; } + + .centered { + width: calc(100% - 350px); + height: calc(100% - 100px); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + .main { + width: 300px; + } + + .new-screen-text { + width: 160px; + text-align: center; + color: #2c2c2c; + font-weight: 600; + } + + .new-screen-button { + margin-left: 5px; + height: 20px; + width: 100px; + display: flex; + align-items: center; + } + + .img-size { + width: 160px; + height: 160px; + } + + .background-icon { + margin-top: 4px; + margin-right: 4px; + } From 15e8b64e6e9763cb4549c6637b0977174cc07886 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 19 Jan 2022 19:45:19 +0000 Subject: [PATCH 11/21] fix export button size --- .../builder/src/pages/builder/portal/apps/index.svelte | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index e7b2724de0..4be0842ec3 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -303,7 +303,13 @@
{#if cloud} - {/if} @@ -403,7 +409,7 @@ logo
- LET’S GET STARTED! + Create a business app in minutes!