- {#if type !== "boolean"}
+ {#if type !== "boolean" && label}
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js
new file mode 100644
index 0000000000..8435971714
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/componentSettings.js
@@ -0,0 +1,54 @@
+import { Checkbox, Input, Select } from "@budibase/bbui"
+import DataSourceSelect from "./DataSourceSelect.svelte"
+import DataProviderSelect from "./DataProviderSelect.svelte"
+import EventsEditor from "./EventsEditor"
+import TableSelect from "./TableSelect.svelte"
+import ColorPicker from "./ColorPicker.svelte"
+import { IconSelect } from "./IconSelect"
+import FieldSelect from "./FieldSelect.svelte"
+import MultiFieldSelect from "./MultiFieldSelect.svelte"
+import SchemaSelect from "./SchemaSelect.svelte"
+import SectionSelect from "./SectionSelect.svelte"
+import NavigationEditor from "./NavigationEditor/NavigationEditor.svelte"
+import FilterEditor from "./FilterEditor/FilterEditor.svelte"
+import URLSelect from "./URLSelect.svelte"
+import StringFieldSelect from "./StringFieldSelect.svelte"
+import NumberFieldSelect from "./NumberFieldSelect.svelte"
+import OptionsFieldSelect from "./OptionsFieldSelect.svelte"
+import BooleanFieldSelect from "./BooleanFieldSelect.svelte"
+import LongFormFieldSelect from "./LongFormFieldSelect.svelte"
+import DateTimeFieldSelect from "./DateTimeFieldSelect.svelte"
+import AttachmentFieldSelect from "./AttachmentFieldSelect.svelte"
+import RelationshipFieldSelect from "./RelationshipFieldSelect.svelte"
+
+const componentMap = {
+ text: Input,
+ select: Select,
+ dataSource: DataSourceSelect,
+ dataProvider: DataProviderSelect,
+ boolean: Checkbox,
+ number: Input,
+ event: EventsEditor,
+ table: TableSelect,
+ color: ColorPicker,
+ icon: IconSelect,
+ field: FieldSelect,
+ multifield: MultiFieldSelect,
+ schema: SchemaSelect,
+ section: SectionSelect,
+ navigation: NavigationEditor,
+ filter: FilterEditor,
+ url: URLSelect,
+ "field/string": StringFieldSelect,
+ "field/number": NumberFieldSelect,
+ "field/options": OptionsFieldSelect,
+ "field/boolean": BooleanFieldSelect,
+ "field/longform": LongFormFieldSelect,
+ "field/datetime": DateTimeFieldSelect,
+ "field/attachment": AttachmentFieldSelect,
+ "field/link": RelationshipFieldSelect,
+}
+
+export const getComponentForSettingType = type => {
+ return componentMap[type]
+}
diff --git a/packages/builder/src/helpers/lucene.js b/packages/builder/src/helpers/lucene.js
new file mode 100644
index 0000000000..43fb155e14
--- /dev/null
+++ b/packages/builder/src/helpers/lucene.js
@@ -0,0 +1,80 @@
+export const OperatorOptions = {
+ Equals: {
+ value: "equal",
+ label: "Equals",
+ },
+ NotEquals: {
+ value: "notEqual",
+ label: "Not equals",
+ },
+ Empty: {
+ value: "empty",
+ label: "Is empty",
+ },
+ NotEmpty: {
+ value: "notEmpty",
+ label: "Is not empty",
+ },
+ StartsWith: {
+ value: "string",
+ label: "Starts with",
+ },
+ Like: {
+ value: "fuzzy",
+ label: "Like",
+ },
+ MoreThan: {
+ value: "rangeLow",
+ label: "More than",
+ },
+ LessThan: {
+ value: "rangeHigh",
+ label: "Less than",
+ },
+}
+
+export const getValidOperatorsForType = type => {
+ const Op = OperatorOptions
+ if (type === "string") {
+ return [
+ Op.Equals,
+ Op.NotEquals,
+ Op.StartsWith,
+ Op.Like,
+ Op.Empty,
+ Op.NotEmpty,
+ ]
+ } else if (type === "number") {
+ return [
+ Op.Equals,
+ Op.NotEquals,
+ Op.MoreThan,
+ Op.LessThan,
+ Op.Empty,
+ Op.NotEmpty,
+ ]
+ } else if (type === "options") {
+ return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty]
+ } else if (type === "boolean") {
+ return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty]
+ } else if (type === "longform") {
+ return [
+ Op.Equals,
+ Op.NotEquals,
+ Op.StartsWith,
+ Op.Like,
+ Op.Empty,
+ Op.NotEmpty,
+ ]
+ } else if (type === "datetime") {
+ return [
+ Op.Equals,
+ Op.NotEquals,
+ Op.MoreThan,
+ Op.LessThan,
+ Op.Empty,
+ Op.NotEmpty,
+ ]
+ }
+ return []
+}
diff --git a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte
index feb15d00bb..d1aaeb0240 100644
--- a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte
@@ -58,5 +58,6 @@
align-items: stretch;
gap: var(--spacing-l);
background-color: var(--background);
+ overflow-y: auto;
}
diff --git a/packages/builder/src/pages/builder/portal/manage/users/[userId].svelte b/packages/builder/src/pages/builder/portal/manage/users/[userId].svelte
index 43360ddf51..c0f21bb554 100644
--- a/packages/builder/src/pages/builder/portal/manage/users/[userId].svelte
+++ b/packages/builder/src/pages/builder/portal/manage/users/[userId].svelte
@@ -19,7 +19,8 @@
import { fetchData } from "helpers"
import { users, auth } from "stores/portal"
- import TagsRenderer from "./_components/TagsTableRenderer.svelte"
+ import TagsRenderer from "./_components/RolesTagsTableRenderer.svelte"
+
import UpdateRolesModal from "./_components/UpdateRolesModal.svelte"
import ForceResetPasswordModal from "./_components/ForceResetPasswordModal.svelte"
@@ -36,7 +37,8 @@
$: defaultRoleId = $userFetch?.data?.builder?.global ? "ADMIN" : "BASIC"
// Merge the Apps list and the roles response to get something that makes sense for the table
$: appList = Object.keys($apps?.data).map(id => {
- const role = $userFetch?.data?.roles?.[id] || defaultRoleId
+ const roleId = $userFetch?.data?.roles?.[id] || defaultRoleId
+ const role = $apps?.data?.[id].roles.find(role => role._id === roleId)
return {
...$apps?.data?.[id],
_id: id,
diff --git a/packages/builder/src/pages/builder/portal/manage/users/_components/RolesTagsTableRenderer.svelte b/packages/builder/src/pages/builder/portal/manage/users/_components/RolesTagsTableRenderer.svelte
new file mode 100644
index 0000000000..7e63045edd
--- /dev/null
+++ b/packages/builder/src/pages/builder/portal/manage/users/_components/RolesTagsTableRenderer.svelte
@@ -0,0 +1,8 @@
+
+
+
diff --git a/packages/builder/src/pages/builder/portal/manage/users/_components/TagsTableRenderer.svelte b/packages/builder/src/pages/builder/portal/manage/users/_components/TagsTableRenderer.svelte
index eab0ccd19c..d2b56bbf33 100644
--- a/packages/builder/src/pages/builder/portal/manage/users/_components/TagsTableRenderer.svelte
+++ b/packages/builder/src/pages/builder/portal/manage/users/_components/TagsTableRenderer.svelte
@@ -4,9 +4,9 @@
const displayLimit = 5
- $: roles = value?.filter(role => role != null) ?? []
- $: tags = roles.slice(0, displayLimit)
- $: leftover = roles.length - tags.length
+ $: values = value?.filter(value => value != null) ?? []
+ $: tags = values.slice(0, displayLimit)
+ $: leftover = values.length - tags.length
diff --git a/packages/builder/src/pages/builder/portal/manage/users/_components/UpdateRolesModal.svelte b/packages/builder/src/pages/builder/portal/manage/users/_components/UpdateRolesModal.svelte
index 332be8e2d4..59045a1198 100644
--- a/packages/builder/src/pages/builder/portal/manage/users/_components/UpdateRolesModal.svelte
+++ b/packages/builder/src/pages/builder/portal/manage/users/_components/UpdateRolesModal.svelte
@@ -10,8 +10,8 @@
const roles = app.roles
let options = roles
+ .filter(role => role._id !== "PUBLIC")
.map(role => ({ value: role._id, label: role.name }))
- .filter(role => role.value !== "PUBLIC")
let selectedRole = user?.roles?.[app?._id]
async function updateUserRoles() {
@@ -48,5 +48,7 @@
on:change
{options}
label="Role"
+ getOptionLabel={role => role.name}
+ getOptionValue={role => role._id}
/>
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 9e3ac8c9a1..fc3cb22f02 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/cli",
- "version": "0.9.79-alpha.4",
+ "version": "0.9.80-alpha.9",
"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 40fb38ac78..54b2c53bd2 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/client",
- "version": "0.9.79-alpha.4",
+ "version": "0.9.80-alpha.9",
"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.79-alpha.4",
- "@budibase/standard-components": "^0.9.79-alpha.4",
- "@budibase/string-templates": "^0.9.79-alpha.4",
+ "@budibase/bbui": "^0.9.80-alpha.9",
+ "@budibase/standard-components": "^0.9.80-alpha.9",
+ "@budibase/string-templates": "^0.9.80-alpha.9",
"regexparam": "^1.3.0",
"shortid": "^2.2.15",
"svelte-spa-router": "^3.0.5"
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index 4440e83845..8c7437e523 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -8,11 +8,18 @@
import { hashString } from "../utils/hash"
import Manifest from "@budibase/standard-components/manifest.json"
import { Placeholder } from "@budibase/standard-components"
+ import {
+ getActiveConditions,
+ reduceConditionActions,
+ } from "../utils/conditions"
export let instance = {}
- // Props that will be passed to the component instance
- let componentProps
+ // The enriched component settings
+ let enrichedSettings
+
+ // Any prop overrides that need to be applied due to conditional UI
+ let conditionalSettings
// Props are hashed when inside the builder preview and used as a key, so that
// components fully remount whenever any props change
@@ -28,6 +35,9 @@
let lastContextKey
let lastInstanceKey
+ // Visibility flag used by conditional UI
+ let visible = true
+
// Get contexts
const context = getContext("context")
const insideScreenslot = !!getContext("screenslot")
@@ -54,6 +64,8 @@
$builderStore.inBuilder &&
$builderStore.selectedComponentId === instance._id
$: interactive = $builderStore.previewType === "layout" || insideScreenslot
+ $: evaluateConditions(enrichedSettings?._conditions)
+ $: componentSettings = { ...enrichedSettings, ...conditionalSettings }
// Update component context
$: componentStore.set({
@@ -62,14 +74,14 @@
styles: { ...instance._styles, id, empty, interactive },
empty,
selected,
- props: componentProps,
+ props: componentSettings,
name,
})
const getRawProps = instance => {
let validProps = {}
Object.entries(instance)
- .filter(([name]) => !name.startsWith("_"))
+ .filter(([name]) => name === "_conditions" || !name.startsWith("_"))
.forEach(([key, value]) => {
validProps[key] = value
})
@@ -123,34 +135,55 @@
return
}
let propsChanged = false
- if (!componentProps) {
- componentProps = {}
+ if (!enrichedSettings) {
+ enrichedSettings = {}
propsChanged = true
}
Object.keys(enrichedProps).forEach(key => {
- if (!propsAreSame(enrichedProps[key], componentProps[key])) {
+ if (!propsAreSame(enrichedProps[key], enrichedSettings[key])) {
propsChanged = true
- componentProps[key] = enrichedProps[key]
+ enrichedSettings[key] = enrichedProps[key]
}
})
// Update the hash if we're in the builder so we can fully remount this
// component
if (get(builderStore).inBuilder && propsChanged) {
- propsHash = hashString(JSON.stringify(componentProps))
+ propsHash = hashString(JSON.stringify(enrichedSettings))
}
}
+
+ const evaluateConditions = conditions => {
+ if (!conditions?.length) {
+ return
+ }
+
+ // Default visible to false if there is a show condition
+ let nextVisible = !conditions.find(condition => condition.action === "show")
+
+ // Execute conditions and determine settings and visibility changes
+ const activeConditions = getActiveConditions(conditions)
+ const result = reduceConditionActions(activeConditions)
+ if (result.visible != null) {
+ nextVisible = result.visible
+ }
+
+ // Update state from condition results
+ conditionalSettings = result.settingUpdates
+ visible = nextVisible
+ }
-
- {#key propsHash}
- {#if constructor && componentProps}
-
+{#key propsHash}
+ {#if constructor && componentSettings && visible}
+
+
{#if children.length}
{#each children as child (child._id)}
@@ -159,9 +192,9 @@
{/if}
- {/if}
- {/key}
-
+
+ {/if}
+{/key}