diff --git a/lerna.json b/lerna.json index 39bf5529e9..4b95c2bf71 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/auth/package.json b/packages/auth/package.json index 67f729ff48..c851e49f54 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/auth", - "version": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "description": "Authentication middlewares for budibase builder and apps", "main": "src/index.js", "author": "Budibase", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 0c82052395..b90efde5c3 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": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "license": "AGPL-3.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/builder/package.json b/packages/builder/package.json index ab4bae4640..bd7fa1693b 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "license": "AGPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^0.9.105-alpha.12", - "@budibase/client": "^0.9.105-alpha.12", + "@budibase/bbui": "^0.9.105-alpha.15", + "@budibase/client": "^0.9.105-alpha.15", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^0.9.105-alpha.12", + "@budibase/string-templates": "^0.9.105-alpha.15", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditRow.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditRow.svelte index 06ab8fd4a9..ce52287c99 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditRow.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditRow.svelte @@ -31,7 +31,12 @@ .flat() // Prevent modal closing if there were errors return false - } else if (rowResponse.status === 400 || rowResponse.status === 500) { + } else if (rowResponse.status === 400 && rowResponse.validationErrors) { + errors = Object.keys(rowResponse.validationErrors).map(field => ({ + message: `${field} ${rowResponse.validationErrors[field][0]}`, + })) + return false + } else if (rowResponse.status === 500) { errors = [{ message: rowResponse.message }] return false } diff --git a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte index 35a4a9db19..c8e23cc535 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte @@ -32,9 +32,29 @@ if (!control) { return false } - if (setting.dependsOn && isEmpty(componentInstance[setting.dependsOn])) { - return false + + // Parse dependant settings + if (setting.dependsOn) { + let dependantSetting = setting.dependsOn + let dependantValue = null + if (typeof setting.dependsOn === "object") { + dependantSetting = setting.dependsOn.setting + dependantValue = setting.dependsOn.value + } + if (!dependantSetting) { + return false + } + + // If no specific value is depended upon, check if a value exists at all + // for the dependent setting + if (dependantValue == null) { + return !isEmpty(componentInstance[dependantSetting]) + } + + // Otherwise check the value matches + return componentInstance[dependantSetting] === dependantValue } + return true } diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsDrawer.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsDrawer.svelte new file mode 100644 index 0000000000..340c1eb107 --- /dev/null +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsDrawer.svelte @@ -0,0 +1,82 @@ + + + +
+ + {#if !options.length} + Add an option to get started. + {/if} + {#if options?.length} +
+ {#each options as option (option.id)} + + + removeOption(option.id)} + /> + {/each} +
+ {/if} +
+ +
+
+
+
+ + diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsEditor.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsEditor.svelte new file mode 100644 index 0000000000..4d74ea9940 --- /dev/null +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/OptionsEditor/OptionsEditor.svelte @@ -0,0 +1,28 @@ + + +Define Options + + + Define the options for this picker. + + + + diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js index 6cf2d7e056..64668d05c8 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js @@ -12,6 +12,7 @@ import SectionSelect from "./SectionSelect.svelte" import NavigationEditor from "./NavigationEditor/NavigationEditor.svelte" import FilterEditor from "./FilterEditor/FilterEditor.svelte" import URLSelect from "./URLSelect.svelte" +import OptionsEditor from "./OptionsEditor/OptionsEditor.svelte" import FormFieldSelect from "./FormFieldSelect.svelte" import ValidationEditor from "./ValidationEditor/ValidationEditor.svelte" @@ -28,6 +29,7 @@ const componentMap = { icon: IconSelect, field: FieldSelect, multifield: MultiFieldSelect, + options: OptionsEditor, schema: SchemaSelect, section: SectionSelect, navigation: NavigationEditor, diff --git a/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte b/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte index 81c18d9f18..cfe225e0f6 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte @@ -53,7 +53,7 @@ label={def.label} key={def.key} value={deepGet($currentAsset, def.key)} - on:change={event => setAssetProps(def.key, event.detail, def.parser)} + onChange={val => setAssetProps(def.key, val, def.parser)} {bindings} /> {/each} diff --git a/packages/cli/package.json b/packages/cli/package.json index 1e18287965..957bec2ffd 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "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 b53341c980..bd3d068799 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -18,9 +18,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^0.9.105-alpha.12", - "@budibase/standard-components": "^0.9.105-alpha.12", - "@budibase/string-templates": "^0.9.105-alpha.12", + "@budibase/bbui": "^0.9.105-alpha.15", + "@budibase/standard-components": "^0.9.105-alpha.15", + "@budibase/string-templates": "^0.9.105-alpha.15", "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 acd4b1618b..0f170a32f8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "description": "Budibase Web Server", "main": "src/index.js", "repository": { @@ -62,9 +62,9 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { - "@budibase/auth": "^0.9.105-alpha.12", - "@budibase/client": "^0.9.105-alpha.12", - "@budibase/string-templates": "^0.9.105-alpha.12", + "@budibase/auth": "^0.9.105-alpha.15", + "@budibase/client": "^0.9.105-alpha.15", + "@budibase/string-templates": "^0.9.105-alpha.15", "@elastic/elasticsearch": "7.10.0", "@koa/router": "8.0.0", "@sendgrid/mail": "7.1.1", @@ -117,7 +117,7 @@ "devDependencies": { "@babel/core": "^7.14.3", "@babel/preset-env": "^7.14.4", - "@budibase/standard-components": "^0.9.105-alpha.12", + "@budibase/standard-components": "^0.9.105-alpha.15", "@jest/test-sequencer": "^24.8.0", "@types/bull": "^3.15.1", "@types/jest": "^26.0.23", diff --git a/packages/server/src/api/controllers/row/internal.js b/packages/server/src/api/controllers/row/internal.js index 28c88c1eac..e39bc2aff9 100644 --- a/packages/server/src/api/controllers/row/internal.js +++ b/packages/server/src/api/controllers/row/internal.js @@ -57,7 +57,7 @@ exports.patch = async ctx => { }) if (!validateResult.valid) { - throw validateResult.errors + throw { validation: validateResult.errors } } // returned row is cleaned and prepared for writing to DB @@ -105,7 +105,7 @@ exports.save = async function (ctx) { }) if (!validateResult.valid) { - throw validateResult.errors + throw { validation: validateResult.errors } } // make sure link rows are up to date diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js index 81601eea1a..c473bf619b 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.js @@ -58,6 +58,7 @@ router.use(async (ctx, next) => { ctx.body = { message: err.message, status: ctx.status, + validationErrors: err.validation, } if (env.NODE_ENV !== "jest") { ctx.log.error(err) diff --git a/packages/standard-components/manifest.json b/packages/standard-components/manifest.json index 9667db74a3..ad37674a0e 100644 --- a/packages/standard-components/manifest.json +++ b/packages/standard-components/manifest.json @@ -1908,6 +1908,7 @@ "type": "select", "label": "Type", "key": "optionsType", + "defaultValue": "select", "placeholder": "Pick an options type", "options": [ { @@ -1935,6 +1936,62 @@ "key": "disabled", "defaultValue": false }, + { + "type": "select", + "label": "Options source", + "key": "optionsSource", + "defaultValue": "schema", + "placeholder": "Pick an options source", + "options": [ + { + "label": "Schema", + "value": "schema" + }, + { + "label": "Data provider", + "value": "provider" + }, + { + "label": "Custom", + "value": "custom" + } + ] + }, + { + "type": "dataProvider", + "label": "Options Provider", + "key": "dataProvider", + "dependsOn": { + "setting": "optionsSource", + "value": "provider" + } + }, + { + "type": "field", + "label": "Label Column", + "key": "labelColumn", + "dependsOn": { + "setting": "optionsSource", + "value": "provider" + } + }, + { + "type": "field", + "label": "Value Column", + "key": "valueColumn", + "dependsOn": { + "setting": "optionsSource", + "value": "provider" + } + }, + { + "type": "options", + "key": "customOptions", + "dependsOn": { + "setting": "optionsSource", + "value": "custom" + } + }, { "type": "validation/string", "label": "Validation", diff --git a/packages/standard-components/package.json b/packages/standard-components/package.json index b94e1f9a01..771297e80b 100644 --- a/packages/standard-components/package.json +++ b/packages/standard-components/package.json @@ -29,11 +29,11 @@ "keywords": [ "svelte" ], - "version": "0.9.105-alpha.12", + "version": "0.9.105-alpha.15", "license": "MIT", "gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc", "dependencies": { - "@budibase/bbui": "^0.9.105-alpha.12", + "@budibase/bbui": "^0.9.105-alpha.15", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/standard-components/src/forms/OptionsField.svelte b/packages/standard-components/src/forms/OptionsField.svelte index ff6f8aa18b..1cfc8fcd6b 100644 --- a/packages/standard-components/src/forms/OptionsField.svelte +++ b/packages/standard-components/src/forms/OptionsField.svelte @@ -9,10 +9,57 @@ export let optionsType = "select" export let validation export let defaultValue + export let optionsSource = "schema" + export let dataProvider + export let labelColumn + export let valueColumn + export let customOptions let fieldState let fieldApi let fieldSchema + + $: flatOptions = optionsSource == null || optionsSource === "schema" + $: options = getOptions( + optionsSource, + fieldSchema, + dataProvider, + labelColumn, + valueColumn + ) + + const getOptions = ( + optionsSource, + fieldSchema, + dataProvider, + labelColumn, + valueColumn + ) => { + // Take options from schema + if (optionsSource == null || optionsSource === "schema") { + return fieldSchema?.constraints?.inclusion ?? [] + } + + // Extract options from data provider + if (optionsSource === "provider" && valueColumn) { + let optionsSet = {} + dataProvider?.rows?.forEach(row => { + const value = row?.[valueColumn] + if (value) { + const label = row[labelColumn] || value + optionsSet[value] = { value, label } + } + }) + return Object.values(optionsSet) + } + + // Extract custom options + if (optionsSource === "custom" && customOptions) { + return customOptions + } + + return [] + } fieldApi.setValue(e.detail)} + getOptionLabel={flatOptions ? x => x : x => x.label} + getOptionValue={flatOptions ? x => x : x => x.value} /> {:else if optionsType === "autocomplete"}