{title}
@@ -27,7 +22,7 @@
justify-content: flex-start;
align-items: center;
gap: var(--spacing-m);
- padding: var(--spacing-xs) var(--spacing-l);
+ padding: var(--spacing-s) var(--spacing-l);
color: var(--ink);
}
.dropdown-item.disabled,
@@ -35,9 +30,6 @@
pointer-events: none;
color: var(--grey-5);
}
- .dropdown-item.big {
- padding: var(--spacing-s) var(--spacing-l);
- }
.dropdown-item:not(.disabled):hover {
background-color: var(--grey-2);
cursor: pointer;
@@ -65,10 +57,6 @@
}
i {
- padding: 0.5rem;
- background-color: var(--grey-2);
- font-size: 24px;
- border-radius: var(--border-radius-s);
- color: var(--ink);
+ font-size: var(--font-size-m);
}
diff --git a/packages/builder/src/components/userInterface/ComponentSelectionList.svelte b/packages/builder/src/components/design/AppPreview/ComponentSelectionList.svelte
similarity index 56%
rename from packages/builder/src/components/userInterface/ComponentSelectionList.svelte
rename to packages/builder/src/components/design/AppPreview/ComponentSelectionList.svelte
index 60f40be6e2..7ec58fc2c3 100644
--- a/packages/builder/src/components/userInterface/ComponentSelectionList.svelte
+++ b/packages/builder/src/components/design/AppPreview/ComponentSelectionList.svelte
@@ -6,47 +6,62 @@
selectedComponent,
currentAssetId,
} from "builderStore"
- import components from "./temporaryPanelStructure.js"
+ import structure from "./componentStructure.json"
import { DropdownMenu } from "@budibase/bbui"
import { DropdownContainer, DropdownItem } from "components/common/Dropdowns"
- const categories = components.categories
+ $: enrichedStructure = enrichStructure(structure, $store.components)
+
let selectedIndex
let anchors = []
let popover
$: anchor = selectedIndex === -1 ? null : anchors[selectedIndex]
- const close = () => {
- popover.hide()
+ const enrichStructure = (structure, definitions) => {
+ let enrichedStructure = []
+ structure.forEach(item => {
+ if (typeof item === "string") {
+ const def = definitions[`@budibase/standard-components/${item}`]
+ if (def) {
+ enrichedStructure.push({
+ ...def,
+ isCategory: false,
+ })
+ }
+ } else {
+ enrichedStructure.push({
+ ...item,
+ isCategory: true,
+ children: enrichStructure(item.children || [], definitions),
+ })
+ }
+ })
+ return enrichedStructure
}
- const onCategoryChosen = (category, idx) => {
- if (category.isCategory) {
+ const onItemChosen = (item, idx) => {
+ if (item.isCategory) {
+ // Select and open this category
selectedIndex = idx
popover.show()
} else {
- onComponentChosen(category)
+ // Add this component
+ store.actions.components.create(item.component)
+ popover.hide()
}
}
-
- const onComponentChosen = component => {
- store.actions.components.create(component._component, component.presetProps)
- const path = store.actions.components.findRoute($selectedComponent)
- $goto(`./${$currentAssetId}/${path}`)
- close()
- }
- {#each categories as category, idx}
+ {#each enrichedStructure as item, idx}
@@ -56,12 +71,12 @@
{anchor}
align="left">
onCategoryChosen(category, idx)}
+ on:click={() => onItemChosen(item, idx)}
class:active={idx === selectedIndex}>
- {#if category.icon}{/if}
- {category.name}
- {#if category.isCategory}{/if}
+ {#if item.icon}{/if}
+ {item.name}
+ {#if item.isCategory}{/if}
{/each}
@@ -32,12 +32,12 @@
-
- {#if propertyGroupNames.length > 0}
- {#each propertyGroupNames as groupName}
+
+ {#if groups.length > 0}
+ {#each groups as groupName}
c._component === componentInstance._component
- ) || {}
-
- $: panelDefinition =
- componentPropDefinition.properties &&
- componentPropDefinition.properties[selectedCategory.value]
+ $: definition = store.actions.components.getDefinition(
+ $selectedComponent._component
+ )
+ $: isComponentOrScreen =
+ $store.currentView === "component" ||
+ $store.currentFrontEndType === FrontendTypes.SCREEN
+ $: isNotScreenslot = !$selectedComponent._component.endsWith("screenslot")
+ $: showDisplayName = isComponentOrScreen && isNotScreenslot
const onStyleChanged = store.actions.components.updateStyle
const onCustomStyleChanged = store.actions.components.updateCustomStyle
const onResetStyles = store.actions.components.resetStyles
- $: isComponentOrScreen =
- $store.currentView === "component" ||
- $store.currentFrontEndType === FrontendTypes.SCREEN
- $: isNotScreenslot = componentInstance._component !== "##builtin/screenslot"
-
- $: displayName =
- isComponentOrScreen && componentInstance._instanceName && isNotScreenslot
-
function walkProps(component, action) {
action(component)
if (component.children) {
@@ -89,24 +73,23 @@
{categories}
{selectedCategory} />
-{#if displayName}
-
{componentInstance._instanceName}
+{#if showDisplayName}
+ {$selectedComponent._instanceName}
{/if}
{#if selectedCategory.value === 'design'}
{:else if selectedCategory.value === 'settings'}
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/Checkbox.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/Checkbox.svelte
new file mode 100644
index 0000000000..5eaf81cdbc
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/Checkbox.svelte
@@ -0,0 +1,7 @@
+
+
+
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColorPicker.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColorPicker.svelte
new file mode 100644
index 0000000000..63ce8da6c4
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ColorPicker.svelte
@@ -0,0 +1,7 @@
+
+
+
diff --git a/packages/builder/src/components/userInterface/DetailScreenSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DetailScreenSelect.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/DetailScreenSelect.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/DetailScreenSelect.svelte
diff --git a/packages/builder/src/components/userInterface/EventsEditor/EventEditor.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditor.svelte
similarity index 98%
rename from packages/builder/src/components/userInterface/EventsEditor/EventEditor.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditor.svelte
index 5dd8f8a423..f15b87d867 100644
--- a/packages/builder/src/components/userInterface/EventsEditor/EventEditor.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditor.svelte
@@ -13,13 +13,12 @@
const EVENT_TYPE_KEY = "##eventHandlerType"
- export let event
+ export let actions
let addActionButton
let addActionDropdown
let selectedAction
- $: actions = event || []
$: selectedActionComponent =
selectedAction &&
actionTypes.find(t => t.name === selectedAction[EVENT_TYPE_KEY]).component
diff --git a/packages/builder/src/components/userInterface/EventsEditor/EventEditorModal.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditorModal.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/EventsEditor/EventEditorModal.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventEditorModal.svelte
diff --git a/packages/builder/src/components/userInterface/EventsEditor/EventPropertyControl.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventPropertyControl.svelte
similarity index 95%
rename from packages/builder/src/components/userInterface/EventsEditor/EventPropertyControl.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventPropertyControl.svelte
index 0d8c07be6e..241864839a 100644
--- a/packages/builder/src/components/userInterface/EventsEditor/EventPropertyControl.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/EventPropertyControl.svelte
@@ -7,7 +7,7 @@
const dispatch = createEventDispatcher()
- export let value
+ export let value = []
export let name
let drawer
@@ -63,6 +63,6 @@
diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/index.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/index.js
similarity index 100%
rename from packages/builder/src/components/userInterface/EventsEditor/actions/index.js
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/index.js
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/index.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/index.js
new file mode 100644
index 0000000000..8966c4ab26
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/index.js
@@ -0,0 +1,2 @@
+import EventsEditor from "./EventPropertyControl.svelte"
+export default EventsEditor
diff --git a/packages/builder/src/components/userInterface/FlatButton.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButton.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/FlatButton.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButton.svelte
diff --git a/packages/builder/src/components/userInterface/FlatButtonGroup.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButtonGroup.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/FlatButtonGroup.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/FlatButtonGroup.svelte
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/index.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/index.js
new file mode 100644
index 0000000000..5221ae4ef4
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FlatButtonGroup/index.js
@@ -0,0 +1,2 @@
+import FlatButtonGroup from "./FlatButtonGroup.svelte"
+export default FlatButtonGroup
diff --git a/packages/builder/src/components/userInterface/IconSelect/IconSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/IconSelect/IconSelect.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte
diff --git a/packages/builder/src/components/userInterface/IconSelect/icons.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js
similarity index 100%
rename from packages/builder/src/components/userInterface/IconSelect/icons.js
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/icons.js
diff --git a/packages/builder/src/components/userInterface/IconSelect/index.js b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/index.js
similarity index 100%
rename from packages/builder/src/components/userInterface/IconSelect/index.js
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/index.js
diff --git a/packages/builder/src/components/userInterface/PropertyPanelControls/Input.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/Input.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/PropertyPanelControls/Input.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/Input.svelte
diff --git a/packages/builder/src/components/userInterface/LayoutSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/LayoutSelect.svelte
similarity index 84%
rename from packages/builder/src/components/userInterface/LayoutSelect.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/LayoutSelect.svelte
index 71bf7e1163..c85f86f409 100644
--- a/packages/builder/src/components/userInterface/LayoutSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/LayoutSelect.svelte
@@ -1,5 +1,5 @@
-
+
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/DeleteRow.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/DeleteRow.svelte
new file mode 100644
index 0000000000..e61fadd57b
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/DeleteRow.svelte
@@ -0,0 +1,72 @@
+
+
+
+ {#if dataProviderComponents.length === 0}
+
+
+
diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/ExecuteQuery.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/ExecuteQuery.svelte
similarity index 77%
rename from packages/builder/src/components/userInterface/EventsEditor/actions/ExecuteQuery.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/ExecuteQuery.svelte
index 05171a0256..a59f1c4954 100644
--- a/packages/builder/src/components/userInterface/EventsEditor/actions/ExecuteQuery.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/ExecuteQuery.svelte
@@ -1,22 +1,18 @@
+
+
+ Delete row can only be used within a component that provides data, such as
+ a List
+
+ {:else}
+
+
+ {/if}
+
+ {#if !dataProviderComponents.length}
+
+ {/if}
+ {/if}
+
+
+
diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/TriggerAutomation.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/TriggerAutomation.svelte
similarity index 98%
rename from packages/builder/src/components/userInterface/EventsEditor/actions/TriggerAutomation.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/TriggerAutomation.svelte
index 18431daf0a..3f61bbcb7e 100644
--- a/packages/builder/src/components/userInterface/EventsEditor/actions/TriggerAutomation.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/TriggerAutomation.svelte
@@ -91,7 +91,6 @@
{/if}
+ Save Row can only be used within a component that provides data, such as a
+ Repeater
+
+ {:else}
+
+
+
+ {#if parameters.providerId}
+
@@ -86,13 +68,13 @@
handleChange(key, val)}
- onChange={val => handleChange(key, val)}
+ value={safeValue}
+ on:change={handleChange}
+ onChange={handleChange}
{...props}
name={key} />
- {#if bindable && !key.startsWith('_') && control === Input}
+ {#if bindable && !key.startsWith('_') && type === 'text'}
{/if}
-
@@ -113,7 +94,7 @@
(temporaryBindableValue = e.detail)}
{bindableProperties} />
diff --git a/packages/builder/src/components/userInterface/PropertyGroup.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyGroup.svelte
similarity index 65%
rename from packages/builder/src/components/userInterface/PropertyGroup.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyGroup.svelte
index 69797c4a21..9d0bb4a40d 100644
--- a/packages/builder/src/components/userInterface/PropertyGroup.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyGroup.svelte
@@ -1,5 +1,4 @@
@@ -31,12 +27,13 @@
+{:else}
+
+{/if}
diff --git a/packages/builder/src/components/userInterface/TableViewSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableViewSelect.svelte
similarity index 78%
rename from packages/builder/src/components/userInterface/TableViewSelect.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableViewSelect.svelte
index 7909a06473..4e5201a180 100644
--- a/packages/builder/src/components/userInterface/TableViewSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableViewSelect.svelte
@@ -1,4 +1,5 @@
+
+
-{:else}
-
-{/if}
diff --git a/packages/builder/src/components/userInterface/assetParsing/createProps.js b/packages/builder/src/components/userInterface/assetParsing/createProps.js
deleted file mode 100644
index 0bd2a4aa15..0000000000
--- a/packages/builder/src/components/userInterface/assetParsing/createProps.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { isString, isUndefined, cloneDeep } from "lodash/fp"
-import { TYPE_MAP } from "./types"
-import { assign } from "lodash"
-import { uuid } from "builderStore/uuid"
-
-export const getBuiltin = _component => {
- const { props } = createProps({ _component })
-
- return {
- _component,
- name: "Screenslot",
- props,
- }
-}
-
-/**
- * @param {object} componentDefinition - component definition from a component library
- * @param {object} derivedFromProps - extra props derived from a components given props.
- * @return {object} the fully created properties for the component, and any property parsing errors
- */
-export const createProps = (componentDefinition, derivedFromProps) => {
- const errorOccurred = (propName, error) => errors.push({ propName, error })
-
- const props = {
- _id: uuid(),
- _component: componentDefinition._component,
- _styles: { normal: {}, hover: {}, active: {} },
- }
-
- const errors = []
-
- if (!componentDefinition._component) {
- errorOccurred("_component", "Component name not supplied")
- }
-
- for (let propName in componentDefinition.props) {
- const parsedPropDef = parsePropDef(componentDefinition.props[propName])
-
- if (parsedPropDef.error) {
- errors.push({ propName, error: parsedPropDef.error })
- } else {
- props[propName] = parsedPropDef
- }
- }
-
- if (derivedFromProps) {
- assign(props, derivedFromProps)
- }
-
- if (isUndefined(props._children)) {
- props._children = []
- }
-
- return {
- props,
- errors,
- }
-}
-
-export const makePropsSafe = (componentDefinition, props) => {
- if (!componentDefinition) {
- console.error(
- "No component definition passed to makePropsSafe. Please check the component definition is being passed correctly."
- )
- }
- const safeProps = createProps(componentDefinition, props).props
- for (let propName in safeProps) {
- props[propName] = safeProps[propName]
- }
-
- for (let propName in props) {
- if (safeProps[propName] === undefined) {
- delete props[propName]
- }
- }
-
- if (!props._styles) {
- props._styles = { normal: {}, hover: {}, active: {} }
- }
-
- return props
-}
-
-const parsePropDef = propDef => {
- const error = message => ({ error: message, propDef })
-
- if (isString(propDef)) {
- if (!TYPE_MAP[propDef]) return error(`Type ${propDef} is not recognised.`)
-
- return cloneDeep(TYPE_MAP[propDef].default)
- }
-
- const type = TYPE_MAP[propDef.type]
- if (!type) return error(`Type ${propDef.type} is not recognised.`)
-
- return cloneDeep(propDef.default)
-}
diff --git a/packages/builder/src/components/userInterface/assetParsing/getRootComponent.js b/packages/builder/src/components/userInterface/assetParsing/getRootComponent.js
deleted file mode 100644
index adaed50299..0000000000
--- a/packages/builder/src/components/userInterface/assetParsing/getRootComponent.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { isRootComponent } from "./searchComponents"
-import { find } from "lodash/fp"
-
-export const getRootComponent = (componentName, components) => {
- const component = find(c => c.name === componentName)(components)
-
- if (isRootComponent(component)) return component
-
- return getRootComponent(component.props._component, components)
-}
diff --git a/packages/builder/src/components/userInterface/assetParsing/searchComponents.js b/packages/builder/src/components/userInterface/assetParsing/searchComponents.js
deleted file mode 100644
index 66ece481f2..0000000000
--- a/packages/builder/src/components/userInterface/assetParsing/searchComponents.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { isUndefined, filter, some, includes } from "lodash/fp"
-import { pipe } from "../../../helpers"
-
-const normalString = s => (s || "").trim().toLowerCase()
-
-export const isRootComponent = c =>
- isComponent(c) && isUndefined(c.props._component)
-
-export const isComponent = c => {
- const hasProp = n => !isUndefined(c[n])
- return hasProp("name") && hasProp("props")
-}
-
-export const searchAllComponents = (components, phrase) => {
- const hasPhrase = (...vals) =>
- pipe(vals, [some(v => includes(normalString(phrase))(normalString(v)))])
-
- const componentMatches = c => {
- if (hasPhrase(c._instanceName, ...(c.tags || []))) return true
-
- if (isRootComponent(c)) return false
-
- const parent = getExactComponent(components, c.props._component)
-
- return componentMatches(parent)
- }
-
- return filter(componentMatches)(components)
-}
-
-export const getExactComponent = (components, name, isScreen = false) => {
- return components.find(comp =>
- isScreen ? comp.props._instanceName === name : comp._instanceName === name
- )
-}
-
-export const getAncestorProps = (components, name, found = []) => {
- const thisComponent = getExactComponent(components, name)
-
- if (isRootComponent(thisComponent)) return [thisComponent.props, ...found]
-
- return getAncestorProps(components, thisComponent.props._component, [
- { ...thisComponent.props },
- ...found,
- ])
-}
diff --git a/packages/builder/src/components/userInterface/assetParsing/splitRootComponentName.js b/packages/builder/src/components/userInterface/assetParsing/splitRootComponentName.js
deleted file mode 100644
index 1776ddf230..0000000000
--- a/packages/builder/src/components/userInterface/assetParsing/splitRootComponentName.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { split, last } from "lodash/fp"
-import { pipe } from "../../../helpers"
-
-export const splitName = fullname => {
- const componentName = pipe(fullname, [split("/"), last])
-
- const libName = fullname.substring(
- 0,
- fullname.length - componentName.length - 1
- )
-
- return { libName, componentName }
-}
diff --git a/packages/builder/src/components/userInterface/assetParsing/types.js b/packages/builder/src/components/userInterface/assetParsing/types.js
deleted file mode 100644
index 9050cb72b7..0000000000
--- a/packages/builder/src/components/userInterface/assetParsing/types.js
+++ /dev/null
@@ -1,25 +0,0 @@
-export const TYPE_MAP = {
- string: {
- default: "",
- },
- bool: {
- default: false,
- },
- number: {
- default: 0,
- },
- options: {
- default: [],
- },
- event: {
- default: [],
- },
- state: {
- default: {
- "##bbstate": "",
- },
- },
- tables: {
- default: {},
- },
-}
diff --git a/packages/builder/src/components/userInterface/temporaryPanelStructure.js b/packages/builder/src/components/userInterface/temporaryPanelStructure.js
deleted file mode 100644
index d41491d56a..0000000000
--- a/packages/builder/src/components/userInterface/temporaryPanelStructure.js
+++ /dev/null
@@ -1,1286 +0,0 @@
-import Input from "./PropertyPanelControls/Input.svelte"
-import OptionSelect from "./OptionSelect.svelte"
-import MultiTableViewFieldSelect from "./MultiTableViewFieldSelect.svelte"
-import Checkbox from "../common/Checkbox.svelte"
-import TableSelect from "components/userInterface/TableSelect.svelte"
-import TableViewSelect from "components/userInterface/TableViewSelect.svelte"
-import TableViewFieldSelect from "components/userInterface/TableViewFieldSelect.svelte"
-import Event from "components/userInterface/EventsEditor/EventPropertyControl.svelte"
-import ScreenSelect from "components/userInterface/ScreenSelect.svelte"
-import DetailScreenSelect from "components/userInterface/DetailScreenSelect.svelte"
-import { IconSelect } from "components/userInterface/IconSelect"
-import Colorpicker from "@budibase/colorpicker"
-
-import { all } from "./propertyCategories.js"
-/*
-{ label: "N/A ", value: "N/A" },
-{ label: "Flex", value: "flex" },
-{ label: "Inline Flex", value: "inline-flex" },
-*/
-
-export default {
- categories: [
- {
- _component: "@budibase/standard-components/container",
- name: "Container",
- description: "This component contains things within itself",
- icon: "ri-layout-column-line",
- commonProps: {},
- children: [],
- properties: {
- design: { ...all },
- settings: [
- {
- key: "type",
- label: "Type",
- control: OptionSelect,
- options: [
- "article",
- "aside",
- "details",
- "div",
- "figure",
- "figcaption",
- "footer",
- "header",
- "main",
- "mark",
- "nav",
- "paragraph",
- "summary",
- ],
- },
- ],
- },
- },
- {
- name: "Grid",
- _component: "@budibase/standard-components/datagrid",
- description:
- "a datagrid component with functionality to add, remove and edit rows.",
- icon: "ri-grid-line",
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Source",
- key: "datasource",
- control: TableViewSelect,
- },
- {
- label: "Detail URL",
- key: "detailUrl",
- control: DetailScreenSelect,
- },
- {
- label: "Editable",
- key: "editable",
- valueKey: "checked",
- control: Checkbox,
- },
- {
- label: "Theme",
- key: "theme",
- control: OptionSelect,
- options: [
- "alpine",
- "alpine-dark",
- "balham",
- "balham-dark",
- "material",
- ],
- placeholder: "alpine",
- },
- {
- label: "Height",
- key: "height",
- defaultValue: "500",
- control: Input,
- },
- {
- label: "Pagination",
- key: "pagination",
- valueKey: "checked",
- control: Checkbox,
- },
- ],
- },
- children: [],
- },
- {
- name: "Repeater",
- _component: "@budibase/standard-components/list",
- description: "Renders all children once per row, of a given table",
- icon: "ri-list-check-2",
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Data",
- key: "datasource",
- control: TableViewSelect,
- },
- ],
- },
- children: [],
- },
- {
- _component: "@budibase/standard-components/button",
- name: "Button",
- description: "A basic html button that is ready for styling",
- icon: "ri-share-box-line",
- children: [],
- properties: {
- design: {
- ...all,
- },
- settings: [
- { label: "Text", key: "text", control: Input },
- {
- label: "Disabled",
- key: "disabled",
- valueKey: "checked",
- control: Checkbox,
- },
- { label: "On Click", key: "onClick", control: Event },
- ],
- },
- },
- {
- name: "Form",
- icon: "ri-file-edit-line",
- isCategory: true,
- children: [
- {
- _component: "@budibase/standard-components/dataform",
- name: "Form Basic",
- icon: "ri-file-edit-line",
- properties: {
- design: { ...all },
- settings: [],
- },
- },
- {
- _component: "@budibase/standard-components/dataformwide",
- name: "Form Wide",
- icon: "ri-file-edit-line",
- properties: {
- design: { ...all },
- settings: [],
- },
- },
- {
- _component: "@budibase/standard-components/input",
- name: "Textfield",
- description:
- "A textfield component that allows the user to input text.",
- icon: "ri-edit-box-line",
- properties: {
- design: { ...all },
- settings: [
- { label: "Label", key: "label", control: Input },
- {
- label: "Type",
- key: "type",
- control: OptionSelect,
- options: ["text", "password"],
- },
- ],
- },
- },
- // {
- // _component: "@budibase/standard-components/richtext",
- // name: "Rich Text",
- // description:
- // "A component that allows the user to enter long form text.",
- // icon: "ri-edit-box-line",
- // properties: {
- // design: { ...all },
- // settings: [],
- // },
- // },
- {
- _component: "@budibase/standard-components/datepicker",
- name: "Date Picker",
- description: "A basic date picker component",
- icon: "ri-calendar-line",
- children: [],
- properties: {
- design: { ...all },
- settings: [
- { label: "Placeholder", key: "placeholder", control: Input },
- ],
- },
- },
- ],
- },
- {
- name: "Card",
- icon: "ri-archive-drawer-line",
- isCategory: true,
- children: [
- {
- _component: "@budibase/standard-components/stackedlist",
- name: "Stacked List",
- icon: "ri-archive-drawer-line",
- description:
- "A basic card component that can contain content and actions.",
- children: [],
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Image",
- key: "imageUrl",
- control: Input,
- placeholder: "{{{context.Image}}}",
- },
- {
- label: "Heading",
- key: "heading",
- control: Input,
- placeholder: "{{context.Heading}}",
- },
- {
- label: "Text 1",
- key: "text1",
- control: Input,
- placeholder: "{{context.Text 1}}",
- },
- {
- label: "Text 2",
- key: "text2",
- control: Input,
- placeholder: "{{context.Text 2}}",
- },
- {
- label: "Text 3",
- key: "text3",
- control: Input,
- placeholder: "{{context.Text 3}}",
- },
- {
- label: "Link URL",
- key: "destinationUrl",
- control: ScreenSelect,
- placeholder: "/table/_id",
- },
- ],
- },
- },
- {
- _component: "@budibase/standard-components/card",
- name: "Vertical",
- description:
- "A basic card component that can contain content and actions.",
- icon: "ri-layout-column-line",
- children: [],
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Image",
- key: "imageUrl",
- control: Input,
- placeholder: "Image",
- },
- {
- label: "Heading",
- key: "heading",
- control: Input,
- placeholder: "Heading",
- },
- {
- label: "Description",
- key: "description",
- control: Input,
- placeholder: "Description",
- },
- {
- label: "Link Text",
- key: "linkText",
- control: Input,
- placeholder: "Link Text",
- },
- {
- label: "Link Url",
- key: "linkUrl",
- control: ScreenSelect,
- placeholder: "Link URL",
- },
- {
- label: "Link Color",
- key: "linkColor",
- control: Colorpicker,
- defaultValue: "#000",
- },
- {
- label: "Hover Color",
- key: "linkHoverColor",
- control: Colorpicker,
- defaultValue: "#222",
- },
- {
- label: "Image Height",
- key: "imageHeight",
- control: OptionSelect,
- options: ["12rem", "16rem", "20rem", "24rem"],
- placeholder: "Image Height",
- },
- {
- label: "Card Width",
- key: "cardWidth",
- control: OptionSelect,
- options: ["16rem", "20rem", "24rem"],
- placeholder: "Card Width",
- },
- ],
- },
- },
- {
- _component: "@budibase/standard-components/cardhorizontal",
- name: "Horizontal",
- description:
- "A basic card component that can contain content and actions.",
- icon: "ri-layout-row-line",
- children: [],
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Image",
- key: "imageUrl",
- control: Input,
- placeholder: "Image",
- },
- {
- label: "Heading",
- key: "heading",
- control: Input,
- placeholder: "Heading",
- },
- {
- label: "Description",
- key: "description",
- control: Input,
- placeholder: "Description",
- },
- {
- label: "Subtext",
- key: "subtext",
- control: Input,
- placeholder: "Subtext",
- },
- {
- label: "Link Text",
- key: "linkText",
- control: Input,
- placeholder: "Link Text",
- },
- {
- label: "Link Url",
- key: "linkUrl",
- control: ScreenSelect,
- placeholder: "Link URL",
- },
- {
- label: "Link Color",
- key: "linkColor",
- control: Colorpicker,
- defaultValue: "#000",
- },
- {
- label: "Hover Color",
- key: "linkHoverColor",
- control: Colorpicker,
- defaultValue: "#222",
- },
- {
- label: "Card Width",
- key: "cardWidth",
- control: OptionSelect,
- options: [
- "24rem",
- "28rem",
- "32rem",
- "40rem",
- "48rem",
- "60rem",
- "100%",
- ],
- placeholder: "Card Height",
- },
- {
- label: "Image Width",
- key: "imageWidth",
- control: OptionSelect,
- options: ["8rem", "12rem", "16rem"],
- placeholder: "Image Width",
- },
- {
- label: "Image Height",
- key: "imageHeight",
- control: OptionSelect,
- options: ["8rem", "12rem", "16rem", "auto"],
- placeholder: "Image Height",
- },
- ],
- },
- },
- {
- _component: "@budibase/standard-components/cardstat",
- name: "Stat",
- description: "A card component for displaying numbers.",
- icon: "ri-dual-sim-2-line",
- children: [],
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Title",
- key: "title",
- control: Input,
- placeholder: "Total Revenue",
- },
- {
- label: "Value",
- key: "value",
- control: Input,
- placeholder: "$1,981,983",
- },
- {
- label: "Label",
- key: "label",
- control: Input,
- placeholder: "Stripe",
- },
- ],
- },
- },
- ],
- },
- {
- name: "Chart",
- icon: "ri-bar-chart-2-line",
- isCategory: true,
- children: [
- {
- name: "Bar Chart",
- _component: "@budibase/standard-components/bar",
- description: "Bar chart",
- icon: "ri-bar-chart-line",
- properties: {
- settings: [
- {
- label: "Title",
- key: "title",
- control: Input,
- },
- {
- label: "Data",
- key: "datasource",
- control: TableViewSelect,
- },
- {
- label: "Label Col.",
- key: "labelColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Data Cols.",
- key: "valueColumns",
- dependsOn: "datasource",
- control: MultiTableViewFieldSelect,
- },
- {
- label: "Format",
- key: "yAxisUnits",
- control: OptionSelect,
- options: ["Default", "Thousands", "Millions"],
- defaultValue: "Default",
- },
- {
- label: "Y Axis Label",
- key: "yAxisLabel",
- control: Input,
- },
- {
- label: "X Axis Label",
- key: "xAxisLabel",
- control: Input,
- },
- {
- label: "Width",
- key: "width",
- control: Input,
- },
- {
- label: "Height",
- key: "height",
- control: Input,
- defaultValue: "400",
- },
- {
- label: "Colours",
- key: "palette",
- control: OptionSelect,
- defaultValue: "Palette 1",
- options: [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10",
- ],
- },
- {
- label: "Stacked",
- key: "stacked",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- {
- label: "Data Labels",
- key: "dataLabels",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- {
- label: "Animate",
- key: "animate",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- {
- label: "Legend",
- key: "legend",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- ],
- },
- },
- {
- name: "Line Chart",
- _component: "@budibase/standard-components/line",
- description: "Line chart",
- icon: "ri-line-chart-line",
- properties: {
- settings: [
- {
- label: "Title",
- key: "title",
- control: Input,
- },
- {
- label: "Data",
- key: "datasource",
- control: TableViewSelect,
- },
- {
- label: "Label Col.",
- key: "labelColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Data Cols.",
- key: "valueColumns",
- dependsOn: "datasource",
- control: MultiTableViewFieldSelect,
- },
- {
- label: "Format",
- key: "yAxisUnits",
- control: OptionSelect,
- options: ["Default", "Thousands", "Millions"],
- defaultValue: "Default",
- },
- {
- label: "Y Axis Label",
- key: "yAxisLabel",
- control: Input,
- },
- {
- label: "X Axis Label",
- key: "xAxisLabel",
- control: Input,
- },
- {
- label: "Width",
- key: "width",
- control: Input,
- },
- {
- label: "Height",
- key: "height",
- control: Input,
- defaultValue: "400",
- },
- {
- label: "Curve",
- key: "curve",
- control: OptionSelect,
- options: ["Smooth", "Straight", "Stepline"],
- defaultValue: "Smooth",
- },
- {
- label: "Colours",
- key: "palette",
- control: OptionSelect,
- defaultValue: "Palette 1",
- options: [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10",
- ],
- },
- {
- label: "Data Labels",
- key: "dataLabels",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- {
- label: "Animate",
- key: "animate",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- {
- label: "Legend",
- key: "legend",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- ],
- },
- },
- {
- name: "Area Chart",
- _component: "@budibase/standard-components/area",
- description: "Line chart",
- icon: "ri-line-chart-fill",
- properties: {
- settings: [
- {
- label: "Title",
- key: "title",
- control: Input,
- },
- {
- label: "Data",
- key: "datasource",
- control: TableViewSelect,
- },
- {
- label: "Label Col.",
- key: "labelColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Data Cols.",
- key: "valueColumns",
- dependsOn: "datasource",
- control: MultiTableViewFieldSelect,
- },
- {
- label: "Format",
- key: "yAxisUnits",
- control: OptionSelect,
- options: ["Default", "Thousands", "Millions"],
- defaultValue: "Default",
- },
- {
- label: "Y Label",
- key: "yAxisLabel",
- control: Input,
- },
- {
- label: "X Label",
- key: "xAxisLabel",
- control: Input,
- },
- {
- label: "Width",
- key: "width",
- control: Input,
- },
- {
- label: "Height",
- key: "height",
- control: Input,
- defaultValue: "400",
- },
- {
- label: "Curve",
- key: "curve",
- control: OptionSelect,
- options: ["Smooth", "Straight", "Stepline"],
- defaultValue: "Smooth",
- },
- {
- label: "Colours",
- key: "palette",
- control: OptionSelect,
- defaultValue: "Palette 1",
- options: [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10",
- ],
- },
- {
- label: "Data Labels",
- key: "dataLabels",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- {
- label: "Animate",
- key: "animate",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- {
- label: "Legend",
- key: "legend",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- {
- label: "Stacked",
- key: "stacked",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- {
- label: "Gradient",
- key: "gradient",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- ],
- },
- },
- {
- name: "Pie Chart",
- _component: "@budibase/standard-components/pie",
- description: "Pie chart",
- icon: "ri-pie-chart-line",
- properties: {
- settings: [
- {
- label: "Title",
- key: "title",
- control: Input,
- },
- {
- label: "Data",
- key: "datasource",
- control: TableViewSelect,
- },
- {
- label: "Label Col.",
- key: "labelColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Data Col.",
- key: "valueColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Width",
- key: "width",
- control: Input,
- },
- {
- label: "Height",
- key: "height",
- control: Input,
- defaultValue: "200",
- },
- {
- label: "Colours",
- key: "palette",
- control: OptionSelect,
- defaultValue: "Palette 1",
- options: [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10",
- ],
- },
- {
- label: "Data Labels",
- key: "dataLabels",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- {
- label: "Animate",
- key: "animate",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- {
- label: "Legend",
- key: "legend",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- ],
- },
- },
- {
- name: "Donut Chart",
- _component: "@budibase/standard-components/donut",
- description: "Donut chart",
- icon: "ri-donut-chart-line",
- properties: {
- settings: [
- {
- label: "Title",
- key: "title",
- control: Input,
- },
- {
- label: "Data",
- key: "datasource",
- control: TableViewSelect,
- },
- {
- label: "Label Col.",
- key: "labelColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Data Col.",
- key: "valueColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Width",
- key: "width",
- control: Input,
- },
- {
- label: "Height",
- key: "height",
- control: Input,
- defaultValue: "200",
- },
- {
- label: "Colours",
- key: "palette",
- control: OptionSelect,
- defaultValue: "Palette 1",
- options: [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10",
- ],
- },
- {
- label: "Data Labels",
- key: "dataLabels",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: false,
- },
- {
- label: "Animate",
- key: "animate",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- {
- label: "Legend",
- key: "legend",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- ],
- },
- },
- {
- name: "Candlestick Chart",
- _component: "@budibase/standard-components/candlestick",
- description: "Candlestick chart",
- icon: "ri-stock-line",
- properties: {
- settings: [
- {
- label: "Title",
- key: "title",
- control: Input,
- },
- {
- label: "Data",
- key: "datasource",
- control: TableViewSelect,
- },
- {
- label: "Date Col.",
- key: "dateColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Open Col.",
- key: "openColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Close Col.",
- key: "closeColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "High Col.",
- key: "highColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Low Col.",
- key: "lowColumn",
- dependsOn: "datasource",
- control: TableViewFieldSelect,
- },
- {
- label: "Format",
- key: "yAxisUnits",
- control: OptionSelect,
- options: ["Default", "Thousands", "Millions"],
- defaultValue: "Default",
- },
- {
- label: "Y Axis Label",
- key: "yAxisLabel",
- control: Input,
- },
- {
- label: "X Axis Label",
- key: "xAxisLabel",
- control: Input,
- },
- {
- label: "Width",
- key: "width",
- control: Input,
- },
- {
- label: "Height",
- key: "height",
- control: Input,
- defaultValue: "400",
- },
- {
- label: "Animate",
- key: "animate",
- control: Checkbox,
- valueKey: "checked",
- defaultValue: true,
- },
- ],
- },
- },
- ],
- },
- {
- name: "Elements",
- icon: "ri-paragraph",
- isCategory: true,
- children: [
- {
- _component: "@budibase/standard-components/heading",
- name: "Headline",
- icon: "ri-heading",
- description: "A component for displaying heading text",
- properties: {
- design: { ...all },
- settings: [
- {
- key: "text",
- label: "Text",
- control: Input,
- },
- {
- key: "type",
- label: "Type",
- control: OptionSelect,
- options: ["h1", "h2", "h3", "h4", "h5", "h6"],
- },
- ],
- },
- },
- {
- _component: "@budibase/standard-components/text",
- name: "Paragraph",
- description: "A component for displaying paragraph text.",
- icon: "ri-paragraph",
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Text",
- key: "text",
- control: Input,
- },
- {
- label: "Type",
- key: "type",
- control: OptionSelect,
- options: [
- "none",
- "bold",
- "strong",
- "italic",
- "emphasis",
- "mark",
- "small",
- "del",
- "ins",
- "sub",
- "sup",
- ],
- },
- ],
- },
- },
- {
- _component: "@budibase/standard-components/image",
- name: "Image",
- description: "A basic component for displaying images",
- icon: "ri-image-line",
- children: [],
- properties: {
- design: { ...all },
- settings: [{ label: "URL", key: "url", control: Input }],
- },
- },
- {
- _component: "@budibase/standard-components/link",
- name: "Link",
- description: "A basic link component for internal and external links",
- icon: "ri-link",
- children: [],
- properties: {
- design: { ...all },
- settings: [
- { label: "Text", key: "text", control: Input },
- { label: "Url", key: "url", control: ScreenSelect },
- {
- label: "New Tab",
- key: "openInNewTab",
- valueKey: "checked",
- control: Checkbox,
- },
- ],
- },
- },
- {
- _component: "@budibase/standard-components/icon",
- name: "Icon",
- description: "A basic component for displaying icons",
- icon: "ri-sun-fill",
- children: [],
- properties: {
- design: {},
- settings: [
- { label: "Icon", key: "icon", control: IconSelect },
- {
- label: "Size",
- key: "size",
- control: OptionSelect,
- defaultValue: "md",
- options: [
- { value: "ri-xxs", label: "xxs" },
- { value: "ri-xs", label: "xs" },
- { value: "ri-sm", label: "sm" },
- { value: "ri-1x", label: "md" },
- { value: "ri-lg", label: "lg" },
- { value: "ri-xl", label: "xl" },
- { value: "ri-2x", label: "2x" },
- { value: "ri-3x", label: "3x" },
- { value: "ri-4x", label: "4x" },
- { value: "ri-5x", label: "5x" },
- { value: "ri-6x", label: "6x" },
- { value: "ri-7x", label: "7x" },
- { value: "ri-8x", label: "8x" },
- { value: "ri-9x", label: "9x" },
- { value: "ri-10x", label: "10x" },
- ],
- },
- {
- label: "Color",
- key: "color",
- control: Colorpicker,
- defaultValue: "#000",
- },
- ],
- },
- },
- {
- _component: "@budibase/standard-components/embed",
- icon: "ri-code-line",
- name: "Embed",
- description: "Embed content from 3rd party sources",
- properties: {
- design: {
- ...all,
- },
- settings: [{ label: "Embed", key: "embed", control: Input }],
- },
- },
- ],
- },
- {
- name: "Other",
- icon: "ri-more-2-line",
- isCategory: true,
- children: [
- {
- _component: "##builtin/screenslot",
- name: "Screen Slot",
- description:
- "This component is a placeholder for the rendering of a screen within a layout.",
- icon: "ri-crop-2-line",
- properties: { design: { ...all } },
- commonProps: {},
- children: [],
- },
- {
- name: "Nav Bar",
- _component: "@budibase/standard-components/navigation",
- description:
- "A component for handling the navigation within your app.",
- icon: "ri-navigation-line",
- children: [],
- properties: {
- design: { ...all },
- settings: [{ label: "Logo URL", key: "logoUrl", control: Input }],
- },
- },
- {
- name: "Login",
- _component: "@budibase/standard-components/login",
- description:
- "A component that automatically generates a login screen for your app.",
- icon: "ri-login-box-line",
- children: [],
- showOnAsset: ["login-screen"],
- properties: {
- design: { ...all },
- settings: [
- {
- label: "Name",
- key: "name",
- control: Input,
- },
- {
- label: "Logo",
- key: "logo",
- control: Input,
- },
- {
- label: "Title",
- key: "title",
- control: Input,
- },
- {
- label: "Button Text",
- key: "buttonText",
- control: Input,
- },
- ],
- },
- },
- {
- name: "Row Detail",
- _component: "@budibase/standard-components/rowdetail",
- description:
- "Loads a row, using an id from the URL, which can be used with {{ context }}, in children",
- icon: "ri-profile-line",
- properties: {
- design: { ...all },
- settings: [{ label: "Table", key: "table", control: TableSelect }],
- },
- children: [],
- },
- {
- name: "New Row",
- _component: "@budibase/standard-components/newrow",
- description:
- "Sets up a new row for creation, which can be used with {{ context }}, in children",
- icon: "ri-profile-line",
- properties: {
- design: { ...all },
- settings: [{ label: "Table", key: "table", control: TableSelect }],
- },
- children: [],
- },
- ],
- },
- ],
-}
diff --git a/packages/builder/src/pages/[application]/_reset.svelte b/packages/builder/src/pages/[application]/_reset.svelte
index 2d9242c444..71a0e918f2 100644
--- a/packages/builder/src/pages/[application]/_reset.svelte
+++ b/packages/builder/src/pages/[application]/_reset.svelte
@@ -3,7 +3,7 @@
import { Button } from "@budibase/bbui"
import SettingsLink from "components/settings/Link.svelte"
import ThemeEditorDropdown from "components/settings/ThemeEditorDropdown.svelte"
- import FeedbackNavLink from "components/userInterface/Feedback/FeedbackNavLink.svelte"
+ import FeedbackNavLink from "components/feedback/FeedbackNavLink.svelte"
import { get } from "builderStore/api"
import { isActive, goto, layout } from "@sveltech/routify"
diff --git a/packages/builder/src/pages/[application]/deploy/index.svelte b/packages/builder/src/pages/[application]/deploy/index.svelte
index 47ae735af4..b64424bf0d 100644
--- a/packages/builder/src/pages/[application]/deploy/index.svelte
+++ b/packages/builder/src/pages/[application]/deploy/index.svelte
@@ -7,7 +7,7 @@
import Spinner from "components/common/Spinner.svelte"
import DeploymentHistory from "components/deploy/DeploymentHistory.svelte"
import analytics from "analytics"
- import FeedbackIframe from "components/userInterface/Feedback/FeedbackIframe.svelte"
+ import FeedbackIframe from "components/feedback/FeedbackIframe.svelte"
let loading = false
let deployments = []
diff --git a/packages/builder/src/pages/[application]/design/[assetType]/[asset]/_layout.svelte b/packages/builder/src/pages/[application]/design/[assetType]/[asset]/_layout.svelte
deleted file mode 100644
index eb266293d9..0000000000
--- a/packages/builder/src/pages/[application]/design/[assetType]/[asset]/_layout.svelte
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
diff --git a/packages/builder/src/pages/[application]/design/[assetType]/_layout.svelte b/packages/builder/src/pages/[application]/design/[assetType]/_layout.svelte
index 64060ef6b7..ad7df634ef 100644
--- a/packages/builder/src/pages/[application]/design/[assetType]/_layout.svelte
+++ b/packages/builder/src/pages/[application]/design/[assetType]/_layout.svelte
@@ -1,34 +1,134 @@
@@ -49,7 +149,7 @@
{#if $selectedComponent != null}
diff --git a/packages/builder/src/pages/[application]/design/[assetType]/index.svelte b/packages/builder/src/pages/[application]/design/[assetType]/index.svelte
index 30545212a9..f1383c9190 100644
--- a/packages/builder/src/pages/[application]/design/[assetType]/index.svelte
+++ b/packages/builder/src/pages/[application]/design/[assetType]/index.svelte
@@ -1,36 +1,50 @@
diff --git a/packages/builder/tests/createProps.spec.js b/packages/builder/tests/createProps.spec.js
deleted file mode 100644
index 5c555386a3..0000000000
--- a/packages/builder/tests/createProps.spec.js
+++ /dev/null
@@ -1,163 +0,0 @@
-import { createProps } from "../src/components/userInterface/assetParsing/createProps"
-import { keys, some } from "lodash/fp"
-import { stripStandardProps } from "./testData"
-
-describe("createDefaultProps", () => {
- const getcomponent = () => ({
- _component: "some_component",
- name: "some_component",
- props: {
- fieldName: { type: "string", default: "something" },
- },
- })
-
- it("should create a object with single string value, when default string field set", () => {
- const { props, errors } = createProps(getcomponent())
-
- expect(errors).toEqual([])
- expect(props.fieldName).toBeDefined()
- expect(props.fieldName).toBe("something")
- stripStandardProps(props)
- expect(keys(props).length).toBe(3)
- })
-
- it("should set component _component", () => {
- const { props, errors } = createProps(getcomponent())
-
- expect(errors).toEqual([])
- expect(props._component).toBe("some_component")
- })
-
- it("should create a object with single blank string value, when prop definition is 'string' ", () => {
- const comp = getcomponent()
- comp.props.fieldName = "string"
-
- const { props, errors } = createProps(comp)
-
- expect(errors).toEqual([])
- expect(props.fieldName).toBeDefined()
- expect(props.fieldName).toBe("")
- })
-
- it("should create a object with single fals value, when prop definition is 'bool' ", () => {
- const comp = getcomponent()
- comp.props.isVisible = "bool"
-
- const { props, errors } = createProps(comp)
-
- expect(errors).toEqual([])
- expect(props.isVisible).toBeDefined()
- expect(props.isVisible).toBe(false)
- })
-
- it("should create a object with single 0 value, when prop definition is 'number' ", () => {
- const comp = getcomponent()
- comp.props.width = "number"
-
- const { props, errors } = createProps(comp)
-
- expect(errors).toEqual([])
- expect(props.width).toBeDefined()
- expect(props.width).toBe(0)
- })
-
- it("should create a object with empty _children array, when children===true ", () => {
- const comp = getcomponent()
- comp.children = true
-
- const { props, errors } = createProps(comp)
-
- expect(errors).toEqual([])
- expect(props._children).toBeDefined()
- expect(props._children).toEqual([])
- })
-
- it("should create a object with single empty array, when prop definition is 'event' ", () => {
- const comp = getcomponent()
- comp.props.onClick = "event"
-
- const { props, errors } = createProps(comp)
-
- expect(errors).toEqual([])
- expect(props.onClick).toBeDefined()
- expect(props.onClick).toEqual([])
- })
-
- it("should create a object children array when children == true ", () => {
- const comp = getcomponent()
- comp.children = true
-
- const { props, errors } = createProps(comp)
-
- expect(errors).toEqual([])
- expect(props._children).toBeDefined()
- expect(props._children).toEqual([])
- })
-
- it("should always create _children ", () => {
- const comp = getcomponent()
- comp.children = false
-
- const createRes1 = createProps(comp)
-
- expect(createRes1.errors).toEqual([])
- expect(createRes1.props._children).toBeDefined()
-
- const comp2 = getcomponent()
- comp2.children = true
-
- const createRes2 = createProps(comp)
-
- expect(createRes2.errors).toEqual([])
- expect(createRes2.props._children).toBeDefined()
- })
-
- it("should create an object with multiple prop names", () => {
- const comp = getcomponent()
- comp.props.fieldName = "string"
- comp.props.fieldLength = { type: "number", default: 500 }
-
- const { props, errors } = createProps(comp)
-
- expect(errors).toEqual([])
- expect(props.fieldName).toBeDefined()
- expect(props.fieldName).toBe("")
- expect(props.fieldLength).toBeDefined()
- expect(props.fieldLength).toBe(500)
- })
-
- it("should return error when invalid type", () => {
- const comp = getcomponent()
- comp.props.fieldName = "invalid type name"
- comp.props.fieldLength = { type: "invalid type name " }
-
- const { errors } = createProps(comp)
-
- expect(errors.length).toBe(2)
- expect(some(e => e.propName === "fieldName")(errors)).toBeTruthy()
- expect(some(e => e.propName === "fieldLength")(errors)).toBeTruthy()
- })
-
- it("should merge in derived props", () => {
- const comp = getcomponent()
- comp.props.fieldName = "string"
- comp.props.fieldLength = { type: "number", default: 500 }
-
- const derivedFrom = {
- fieldName: "surname",
- }
-
- const { props, errors } = createProps(comp, derivedFrom)
-
- expect(errors.length).toBe(0)
- expect(props.fieldName).toBe("surname")
- expect(props.fieldLength).toBe(500)
- })
-
- it("should create standard props", () => {
- const comp = getcomponent()
- comp.props.fieldName = { type: "string", default: 1 }
- const { props } = createProps(comp)
- expect(props._styles).toBeDefined()
- })
-})
diff --git a/packages/builder/tests/fetchBindableProperties.spec.js b/packages/builder/tests/fetchBindableProperties.spec.js
deleted file mode 100644
index 0122573307..0000000000
--- a/packages/builder/tests/fetchBindableProperties.spec.js
+++ /dev/null
@@ -1,253 +0,0 @@
-import fetchBindableProperties from "../src/builderStore/fetchBindableProperties"
-
-describe("fetch bindable properties", () => {
- it("should return bindable properties from screen components", () => {
- const result = fetchBindableProperties({
- componentInstanceId: "heading-id",
- ...testData(),
- })
- const componentBinding = result.find(
- r => r.instance._id === "search-input-id" && r.type === "instance"
- )
- expect(componentBinding).toBeDefined()
- expect(componentBinding.type).toBe("instance")
- expect(componentBinding.runtimeBinding).toBe("search-input-id")
- })
-
- it("should not return bindable components when not in their context", () => {
- const result = fetchBindableProperties({
- componentInstanceId: "heading-id",
- ...testData(),
- })
- const componentBinding = result.find(
- r => r.instance._id === "list-item-input-id"
- )
- expect(componentBinding).not.toBeDefined()
- })
-
- it("should return table schema, when inside a context", () => {
- const result = fetchBindableProperties({
- componentInstanceId: "list-item-input-id",
- ...testData(),
- })
- const contextBindings = result.filter(
- r => r.instance._id === "list-id" && r.type === "context"
- )
- // 2 fields + _id + _rev
- expect(contextBindings.length).toBe(4)
-
- const namebinding = contextBindings.find(
- b => b.runtimeBinding === "list-id.name"
- )
- expect(namebinding).toBeDefined()
- expect(namebinding.readableBinding).toBe("list-name.Test Table.name")
-
- const descriptionbinding = contextBindings.find(
- b => b.runtimeBinding === "list-id.description"
- )
- expect(descriptionbinding).toBeDefined()
- expect(descriptionbinding.readableBinding).toBe(
- "list-name.Test Table.description"
- )
-
- const idbinding = contextBindings.find(
- b => b.runtimeBinding === "list-id._id"
- )
- expect(idbinding).toBeDefined()
- expect(idbinding.readableBinding).toBe("list-name.Test Table._id")
- })
-
- it("should return table schema, for grantparent context", () => {
- const result = fetchBindableProperties({
- componentInstanceId: "child-list-item-input-id",
- ...testData(),
- })
- const contextBindings = result.filter(r => r.type === "context")
- // 2 fields + _id + _rev ... x 2 tables
- expect(contextBindings.length).toBe(8)
-
- const namebinding_parent = contextBindings.find(
- b => b.runtimeBinding === "list-id.name"
- )
- expect(namebinding_parent).toBeDefined()
- expect(namebinding_parent.readableBinding).toBe("list-name.Test Table.name")
-
- const descriptionbinding_parent = contextBindings.find(
- b => b.runtimeBinding === "list-id.description"
- )
- expect(descriptionbinding_parent).toBeDefined()
- expect(descriptionbinding_parent.readableBinding).toBe(
- "list-name.Test Table.description"
- )
-
- const namebinding_own = contextBindings.find(
- b => b.runtimeBinding === "child-list-id.name"
- )
- expect(namebinding_own).toBeDefined()
- expect(namebinding_own.readableBinding).toBe(
- "child-list-name.Test Table.name"
- )
-
- const descriptionbinding_own = contextBindings.find(
- b => b.runtimeBinding === "child-list-id.description"
- )
- expect(descriptionbinding_own).toBeDefined()
- expect(descriptionbinding_own.readableBinding).toBe(
- "child-list-name.Test Table.description"
- )
- })
-
- it("should return bindable component props, from components in same context", () => {
- const result = fetchBindableProperties({
- componentInstanceId: "list-item-heading-id",
- ...testData(),
- })
- const componentBinding = result.find(
- r => r.instance._id === "list-item-input-id" && r.type === "instance"
- )
- expect(componentBinding).toBeDefined()
- expect(componentBinding.runtimeBinding).toBe("list-item-input-id")
- })
-
- it("should not return components from child context", () => {
- const result = fetchBindableProperties({
- componentInstanceId: "list-item-heading-id",
- ...testData(),
- })
- const componentBinding = result.find(
- r =>
- r.instance._id === "child-list-item-input-id" && r.type === "instance"
- )
- expect(componentBinding).not.toBeDefined()
- })
-
- it("should return bindable component props, from components in same context (when nested context)", () => {
- const result = fetchBindableProperties({
- componentInstanceId: "child-list-item-heading-id",
- ...testData(),
- })
- const componentBinding = result.find(
- r =>
- r.instance._id === "child-list-item-input-id" && r.type === "instance"
- )
- expect(componentBinding).toBeDefined()
- })
-})
-
-const testData = () => {
- const screen = {
- instanceName: "test screen",
- name: "screen-id",
- route: "/",
- props: {
- _id: "screent-root-id",
- _component: "@budibase/standard-components/container",
- _children: [
- {
- _id: "heading-id",
- _instanceName: "list item heading",
- _component: "@budibase/standard-components/heading",
- text: "Screen Title",
- },
- {
- _id: "search-input-id",
- _instanceName: "Search Input",
- _component: "@budibase/standard-components/input",
- value: "search phrase",
- },
- {
- _id: "list-id",
- _component: "@budibase/standard-components/list",
- _instanceName: "list-name",
- table: {
- type: "table",
- tableId: "test-table-id",
- label: "Test Table",
- name: "all_test-table-id",
- },
- _children: [
- {
- _id: "list-item-heading-id",
- _instanceName: "list item heading",
- _component: "@budibase/standard-components/heading",
- text: "hello",
- },
- {
- _id: "list-item-input-id",
- _instanceName: "List Item Input",
- _component: "@budibase/standard-components/input",
- value: "list item",
- },
- {
- _id: "child-list-id",
- _component: "@budibase/standard-components/list",
- _instanceName: "child-list-name",
- table: {
- type: "table",
- tableId: "test-table-id",
- label: "Test Table",
- name: "all_test-table-id",
- },
- _children: [
- {
- _id: "child-list-item-heading-id",
- _instanceName: "child list item heading",
- _component: "@budibase/standard-components/heading",
- text: "hello",
- },
- {
- _id: "child-list-item-input-id",
- _instanceName: "Child List Item Input",
- _component: "@budibase/standard-components/input",
- value: "child list item",
- },
- ],
- },
- ],
- },
- ],
- },
- }
-
- const tables = [
- {
- _id: "test-table-id",
- name: "Test Table",
- schema: {
- name: {
- type: "string",
- },
- description: {
- type: "string",
- },
- },
- },
- ]
-
- const queries = []
-
- const components = {
- "@budibase/standard-components/container": {
- props: {},
- },
- "@budibase/standard-components/list": {
- context: "table",
- props: {
- table: "string",
- },
- },
- "@budibase/standard-components/input": {
- bindable: "value",
- props: {
- value: "string",
- },
- },
- "@budibase/standard-components/heading": {
- props: {
- text: "string",
- },
- },
- }
-
- return { screen, tables, components, queries }
-}
diff --git a/packages/builder/tests/searchComponentsProps.spec.js b/packages/builder/tests/searchComponentsProps.spec.js
deleted file mode 100644
index abf1dad7da..0000000000
--- a/packages/builder/tests/searchComponentsProps.spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import {
- searchAllComponents,
- getExactComponent,
- getAncestorProps,
-} from "../src/components/userInterface/assetParsing/searchComponents"
-import { componentsAndScreens } from "./testData"
-
-
-describe("getExactComponent", () => {
- it("should get component by name", () => {
- const { components } = componentsAndScreens()
- const result = getExactComponent(
- components,
- "TextBox"
- )
-
- expect(result).toBeDefined()
- expect(result._instanceName).toBe("TextBox")
- })
-
- test("Should not find as isScreen is not specified", () => {
- const { screens } = componentsAndScreens()
- const result = getExactComponent(screens, "SmallTextbox")
-
- expect(result).not.toBeDefined()
- })
-
- test("Should find as isScreen is specified", () => {
- const { screens } = componentsAndScreens()
- const result = getExactComponent(screens, "SmallTextbox", true)
-
- expect(result).toBeDefined()
- expect(result.props._instanceName).toBe("SmallTextbox")
-
- })
-})
-
diff --git a/packages/client/src/api/api.js b/packages/client/src/api/api.js
index a88398ed3a..5509221d5c 100644
--- a/packages/client/src/api/api.js
+++ b/packages/client/src/api/api.js
@@ -77,7 +77,7 @@ const makeCachedApiCall = async params => {
const requestApiCall = method => async params => {
const { url, cache = false } = params
const fixedUrl = `/${url}`.replace("//", "/")
- const enrichedParams = { ...params, method, fixedUrl }
+ const enrichedParams = { ...params, method, url: fixedUrl }
return await (cache ? makeCachedApiCall : makeApiCall)(enrichedParams)
}
diff --git a/packages/client/src/api/datasources.js b/packages/client/src/api/datasources.js
index ff91a9f61d..7e5e11cd08 100644
--- a/packages/client/src/api/datasources.js
+++ b/packages/client/src/api/datasources.js
@@ -1,16 +1,14 @@
-import { get } from "svelte/store"
+import { cloneDeep } from "lodash/fp"
import { fetchTableData } from "./tables"
import { fetchViewData } from "./views"
import { fetchRelationshipData } from "./relationships"
import { executeQuery } from "./queries"
import { enrichRows } from "./rows"
-import { enrichDataBindings } from "../utils/enrichDataBinding"
-import { bindingStore } from "../store/binding"
/**
* Fetches all rows for a particular Budibase data source.
*/
-export const fetchDatasource = async (datasource, dataContext) => {
+export const fetchDatasource = async datasource => {
if (!datasource || !datasource.type) {
return []
}
@@ -23,28 +21,22 @@ export const fetchDatasource = async (datasource, dataContext) => {
} else if (type === "view") {
rows = await fetchViewData(datasource)
} else if (type === "query") {
- const bindings = get(bindingStore)
-
// Set the default query params
- let queryParams = datasource.queryParams || {}
+ let parameters = cloneDeep(datasource.queryParams || {})
for (let param of datasource.parameters) {
- if (!queryParams[param.name]) {
- queryParams[param.name] = param.default
+ if (!parameters[param.name]) {
+ parameters[param.name] = param.default
}
}
- const parameters = enrichDataBindings(queryParams, {
- ...bindings,
- ...dataContext,
- })
return await executeQuery({ queryId: datasource._id, parameters })
} else if (type === "link") {
- const row = dataContext[datasource.providerId]
rows = await fetchRelationshipData({
- rowId: row?._id,
- tableId: row?.tableId,
+ rowId: datasource.rowId,
+ tableId: datasource.rowTableId,
fieldName,
})
}
- // Enrich rows
+
+ // Enrich rows so they can displayed properly
return await enrichRows(rows, tableId)
}
diff --git a/packages/client/src/api/queries.js b/packages/client/src/api/queries.js
index 5912524023..4e89921bb6 100644
--- a/packages/client/src/api/queries.js
+++ b/packages/client/src/api/queries.js
@@ -11,8 +11,8 @@ export const executeQuery = async ({ queryId, parameters }) => {
parameters,
},
})
- res.error
- ? notificationStore.danger("An error has occurred")
- : notificationStore.success("Query successful")
+ if (res.error) {
+ notificationStore.danger("An error has occurred")
+ }
return res
}
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index a303b0262f..208ba21718 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -3,11 +3,14 @@
import { writable } from "svelte/store"
import * as ComponentLibrary from "@budibase/standard-components"
import Router from "./Router.svelte"
- import { enrichProps } from "../utils/componentProps"
+ import { enrichProps, propsAreSame } from "../utils/componentProps"
import { bindingStore, builderStore } from "../store"
export let definition = {}
+ let enrichedProps
+ let componentProps
+
// Get contexts
const dataContext = getContext("data")
const screenslotContext = getContext("screenslot")
@@ -16,14 +19,12 @@
const componentStore = writable({})
setContext("component", componentStore)
- // Enrich component props
- let enrichedProps
- $: enrichComponentProps(definition, $dataContext, $bindingStore)
-
// Extract component definition info
$: constructor = getComponentConstructor(definition._component)
- $: children = definition._children
+ $: children = definition._children || []
$: id = definition._id
+ $: enrichComponentProps(definition, $dataContext, $bindingStore)
+ $: updateProps(enrichedProps)
$: styles = definition._styles
// Allow component selection in the builder preview if we're previewing a
@@ -38,11 +39,31 @@
styles: { ...styles, id, allowSelection },
})
+ // Updates the component props.
+ // Most props are deeply compared so that svelte will only trigger reactive
+ // statements on props that have actually changed.
+ const updateProps = props => {
+ if (!props) {
+ return
+ }
+ if (!componentProps) {
+ componentProps = {}
+ }
+ Object.keys(props).forEach(key => {
+ if (!propsAreSame(props[key], componentProps[key])) {
+ componentProps[key] = props[key]
+ }
+ })
+ }
+
// Gets the component constructor for the specified component
const getComponentConstructor = component => {
const split = component?.split("/")
const name = split?.[split.length - 1]
- return name === "screenslot" ? Router : ComponentLibrary[name]
+ if (name === "screenslot" && $builderStore.previewType !== "layout") {
+ return Router
+ }
+ return ComponentLibrary[name]
}
// Enriches any string component props using handlebars
@@ -59,9 +80,9 @@
}
-{#if constructor && enrichedProps}
-
- {#if children && children.length}
+{#if constructor && componentProps}
+
+ {#if children.length}
{#each children as child (getChildKey(child._id))}
{/each}
diff --git a/packages/client/src/sdk.js b/packages/client/src/sdk.js
index 98cff20679..b5efe1257c 100644
--- a/packages/client/src/sdk.js
+++ b/packages/client/src/sdk.js
@@ -5,6 +5,7 @@ import {
routeStore,
screenStore,
bindingStore,
+ builderStore,
} from "./store"
import { styleable } from "./utils/styleable"
import { linkable } from "./utils/linkable"
@@ -16,6 +17,7 @@ export default {
notifications: notificationStore,
routeStore,
screenStore,
+ builderStore,
styleable,
linkable,
DataProvider,
diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js
index 54be3e51be..178abd328d 100644
--- a/packages/client/src/utils/buttonActions.js
+++ b/packages/client/src/utils/buttonActions.js
@@ -1,51 +1,57 @@
+import { get } from "svelte/store"
import { enrichDataBinding, enrichDataBindings } from "./enrichDataBinding"
-import { routeStore } from "../store"
+import { routeStore, builderStore } from "../store"
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "../api"
const saveRowHandler = async (action, context) => {
- let draft = context[`${action.parameters.contextPath}_draft`]
- if (action.parameters.fields) {
- for (let [key, entry] of Object.entries(action.parameters.fields)) {
- draft[key] = await enrichDataBinding(entry.value, context)
+ const { fields, providerId } = action.parameters
+ if (providerId) {
+ let draft = context[`${providerId}_draft`]
+ if (fields) {
+ for (let [key, entry] of Object.entries(fields)) {
+ draft[key] = await enrichDataBinding(entry.value, context)
+ }
}
+ await saveRow(draft)
}
- await saveRow(draft)
}
const deleteRowHandler = async (action, context) => {
const { tableId, revId, rowId } = action.parameters
- const [enrichTable, enrichRow, enrichRev] = await Promise.all([
- enrichDataBinding(tableId, context),
- enrichDataBinding(rowId, context),
- enrichDataBinding(revId, context),
- ])
- await deleteRow({
- tableId: enrichTable,
- rowId: enrichRow,
- revId: enrichRev,
- })
+ if (tableId && revId && rowId) {
+ const [enrichTable, enrichRow, enrichRev] = await Promise.all([
+ enrichDataBinding(tableId, context),
+ enrichDataBinding(rowId, context),
+ enrichDataBinding(revId, context),
+ ])
+ await deleteRow({
+ tableId: enrichTable,
+ rowId: enrichRow,
+ revId: enrichRev,
+ })
+ }
}
const triggerAutomationHandler = async (action, context) => {
- const params = {}
- for (let field in action.parameters.fields) {
- params[field] = await enrichDataBinding(
- action.parameters.fields[field].value,
- context
- )
+ const { fields } = action.parameters()
+ if (fields) {
+ const params = {}
+ for (let field in fields) {
+ params[field] = await enrichDataBinding(fields[field].value, context)
+ }
+ await triggerAutomation(action.parameters.automationId, params)
}
- await triggerAutomation(action.parameters.automationId, params)
}
const navigationHandler = action => {
- routeStore.actions.navigate(action.parameters.url)
+ if (action.parameters.url) {
+ routeStore.actions.navigate(action.parameters.url)
+ }
}
const queryExecutionHandler = async (action, context) => {
const { datasourceId, queryId, queryParams } = action.parameters
-
- const enrichedQueryParameters = enrichDataBindings(queryParams, context)
-
+ const enrichedQueryParameters = enrichDataBindings(queryParams || {}, context)
await executeQuery({
datasourceId,
queryId,
@@ -66,6 +72,10 @@ const handlerMap = {
* actions in the current context.
*/
export const enrichButtonActions = (actions, context) => {
+ // Prevent button actions in the builder preview
+ if (get(builderStore).inBuilder) {
+ return () => {}
+ }
const handlers = actions.map(def => handlerMap[def["##eventHandlerType"]])
return async () => {
for (let i = 0; i < handlers.length; i++) {
diff --git a/packages/client/src/utils/componentProps.js b/packages/client/src/utils/componentProps.js
index 170faf47a1..7b322ec80f 100644
--- a/packages/client/src/utils/componentProps.js
+++ b/packages/client/src/utils/componentProps.js
@@ -1,6 +1,22 @@
import { enrichDataBindings } from "./enrichDataBinding"
import { enrichButtonActions } from "./buttonActions"
+/**
+ * Deeply compares 2 props using JSON.stringify.
+ * Does not consider functions, as currently only button actions have a function
+ * prop and it's cheaper to just always re-render buttons than it is to deeply
+ * compare them.
+ */
+export const propsAreSame = (a, b) => {
+ if (a === b) {
+ return true
+ }
+ if (typeof a === "function" || typeof b === "function") {
+ return false
+ }
+ return JSON.stringify(a) === JSON.stringify(b)
+}
+
/**
* Enriches component props.
* Data bindings are enriched, and button actions are enriched.
diff --git a/packages/client/src/utils/enrichDataBinding.js b/packages/client/src/utils/enrichDataBinding.js
index f6682777b5..b8c5020c74 100644
--- a/packages/client/src/utils/enrichDataBinding.js
+++ b/packages/client/src/utils/enrichDataBinding.js
@@ -1,4 +1,5 @@
-import { processString } from "@budibase/string-templates"
+import { cloneDeep } from "lodash/fp"
+import { processString, processObject } from "@budibase/string-templates"
// Regex to test inputs with to see if they are likely candidates for template strings
const looksLikeTemplate = /{{.*}}/
@@ -19,12 +20,9 @@ export const enrichDataBinding = async (input, context) => {
}
/**
- * Enriches each prop in a props object
+ * Recursively enriches all props in a props object and returns the new props.
+ * Props are deeply cloned so that no mutation is done to the source object.
*/
export const enrichDataBindings = async (props, context) => {
- let enrichedProps = {}
- for (let [key, value] of Object.entries(props)) {
- enrichedProps[key] = await enrichDataBinding(value, context)
- }
- return enrichedProps
+ return await processObject(cloneDeep(props), context)
}
diff --git a/packages/server/src/api/controllers/component.js b/packages/server/src/api/controllers/component.js
index 2d28520609..092d154817 100644
--- a/packages/server/src/api/controllers/component.js
+++ b/packages/server/src/api/controllers/component.js
@@ -21,7 +21,7 @@ exports.fetchAppComponentDefinitions = async function(ctx) {
appDirectory,
componentLibrary,
ctx.isDev ? "" : "package",
- "components.json"
+ "manifest.json"
))
const result = {}
@@ -29,9 +29,9 @@ exports.fetchAppComponentDefinitions = async function(ctx) {
// map over the components.json and add the library identifier as a key
// button -> @budibase/standard-components/button
for (let key of Object.keys(componentJson)) {
- const fullComponentName = `${componentLibrary}/${key}`
+ const fullComponentName = `${componentLibrary}/${key}`.toLowerCase()
result[fullComponentName] = {
- _component: fullComponentName,
+ component: fullComponentName,
...componentJson[key],
}
}
diff --git a/packages/server/src/api/controllers/integration.js b/packages/server/src/api/controllers/integration.js
index edd3eeef25..d8c726c8f3 100644
--- a/packages/server/src/api/controllers/integration.js
+++ b/packages/server/src/api/controllers/integration.js
@@ -2,7 +2,6 @@ const { definitions } = require("../../integrations")
exports.fetch = async function(ctx) {
// TODO: fetch these from a github repo etc
- console.log(definitions)
ctx.status = 200
ctx.body = definitions
}
diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js
index 2096b3039e..4f3d8d1611 100644
--- a/packages/server/src/api/controllers/static/index.js
+++ b/packages/server/src/api/controllers/static/index.js
@@ -177,6 +177,7 @@ exports.serveApp = async function(ctx) {
})
const appHbs = fs.readFileSync(`${__dirname}/templates/app.hbs`, "utf8")
+ console.log(appHbs)
ctx.body = await processString(appHbs, {
head,
body: html,
diff --git a/packages/server/src/constants/layouts.js b/packages/server/src/constants/layouts.js
index 221acb4925..d32ce4453d 100644
--- a/packages/server/src/constants/layouts.js
+++ b/packages/server/src/constants/layouts.js
@@ -16,7 +16,7 @@ const EMPTY_LAYOUT = {
_children: [
{
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
- _component: "##builtin/screenslot",
+ _component: "@budibase/standard-components/screenslot",
_styles: {
normal: {
flex: "1 1 auto",
@@ -152,7 +152,7 @@ const BASE_LAYOUTS = [
},
{
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
- _component: "##builtin/screenslot",
+ _component: "@budibase/standard-components/screenslot",
_styles: {
normal: {
flex: "1 1 auto",
@@ -207,7 +207,7 @@ const BASE_LAYOUTS = [
_children: [
{
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
- _component: "##builtin/screenslot",
+ _component: "@budibase/standard-components/screenslot",
_styles: {
normal: {
flex: "1 1 auto",
diff --git a/packages/standard-components/README.md b/packages/standard-components/README.md
index 71e531fc9d..67729ac3db 100644
--- a/packages/standard-components/README.md
+++ b/packages/standard-components/README.md
@@ -1,33 +1,43 @@
-*Psst — looking for an app template? Go here --> [sveltejs/template](https://github.com/sveltejs/template)*
+## Manifest
----
-
-# component-template
-
-A base for building shareable Svelte components. Clone it with [degit](https://github.com/Rich-Harris/degit):
-
-```bash
-npx degit sveltejs/component-template my-new-component
-cd my-new-component
-npm install # or yarn
-```
-
-Your component's source code lives in `src/index.html`.
-
-TODO
-
-* [ ] some firm opinions about the best way to test components
-* [ ] update `degit` so that it automates some of the setup work
+The `manifest.json` file exports the definitions of all components available in this version
+of the client library. The manifest is used by the builder to correctly display components and
+their settings, and know how to correctly interact with them.
-## Setting up
-* Run `npm init` (or `yarn init`)
-* Replace this README with your own
+### Component Definitions
+
+The object key is the name of the component, as exported by `index.js`.
+
+- **name** - the name displayed in the builder
+- **description** - not currently used
+- **icon** - the icon displayed in the builder
+- **hasChildren** - whether the component accepts children or not
+- **styleable** - whether the component accepts design props or not
+- **dataProvider** - whether the component provides a data context or not
+- **bindable** - whether the components provides a bindable value or not
+- **settings** - array of settings displayed in the builder
+
+###Settings Definitions
+
+The `type` field in each setting is used by the builder to know which component to use to display
+the setting, so it's important that this field is correct. The valid options are:
+
+- **text** - A text field
+- **select** - A select dropdown. Accompany these with an `options` field to provide options
+- **datasource** - A datasource (e.g. a table or a view)
+- **boolean** - A boolean field
+- **number** - A numeric text field
+- **detailURL** - A URL to a page which displays details about a row.
+Exclusively used for grids which link to row details.
-## Consuming components
+The available fields in each setting definition are:
-Your package.json has a `"svelte"` field pointing to `src/index.html`, which allows Svelte apps to import the source code directly, if they are using a bundler plugin like [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) or [svelte-loader](https://github.com/sveltejs/svelte-loader) (where [`resolve.mainFields`](https://webpack.js.org/configuration/resolve/#resolve-mainfields) in your webpack config includes `"svelte"`). **This is recommended.**
-
-For everyone else, `npm run build` will bundle your component's source code into a plain JavaScript module (`index.mjs`) and a UMD script (`index.js`). This will happen automatically when you publish your component to npm, courtesy of the `prepublishOnly` hook in package.json.
+- **type** - the type of field which determines which component the builder will use
+to display the setting
+- **key** - the key of this setting in the component
+- **label** - the label displayed in the builder
+- **defaultValue** - the default value of the setting
+- **placeholder** - the placeholder for the setting
diff --git a/packages/standard-components/components.json b/packages/standard-components/components.json
deleted file mode 100644
index fb924c08ee..0000000000
--- a/packages/standard-components/components.json
+++ /dev/null
@@ -1,678 +0,0 @@
-{
- "_lib": "./dist/index.js",
- "_templates": {
- "saveRowButton": {
- "description": "Save row button",
- "component": "button"
- }
- },
- "embed": {
- "name": "Embed",
- "description": "Embed stuff",
- "props": {
- "embed": "string"
- }
- },
- "navigation": {
- "name": "Navigation",
- "description": "A basic header navigation component",
- "children": true,
- "props": {
- "logoUrl": "string"
- }
- },
- "button": {
- "name": "Button",
- "description": "an html ",
- "props": {
- "text": "string",
- "disabled": "bool",
- "onClick": "event"
- },
- "tags": [
- "layout"
- ],
- "presets": {
- "primary": {
- "contentText": "Primary Button Preset",
- "color": "papayawhip",
- "padding": "20px",
- "background": "blue"
- },
- "secondary": {
- "contentText": "Secondary Button Preset",
- "color": "rebeccapurple",
- "padding": "10px",
- "background": "#fff",
- "border": "1px solid red"
- },
- "error": {
- "contentText": "ERROR",
- "color": "red",
- "padding": "10px",
- "border": "1px solid red"
- }
- }
- },
- "login": {
- "name": "Login Control",
- "description": "A control that accepts email, password an also handles password resets",
- "props": {
- "logo": "string",
- "title": "string",
- "buttonText": "string"
- },
- "tags": [
- "login",
- "credentials",
- "password",
- "logon"
- ]
- },
- "input": {
- "name": "Textfield",
- "bindable": "value",
- "description": "An HTML input",
- "props": {
- "type": {
- "type": "options",
- "options": [
- "text",
- "password",
- "checkbox",
- "color",
- "date",
- "datetime-local",
- "email",
- "file",
- "hidden",
- "image",
- "month",
- "number",
- "radio",
- "range",
- "reset",
- "search",
- "submit",
- "tel",
- "time",
- "week"
- ],
- "default": "text"
- }
- },
- "tags": [
- "form"
- ]
- },
- "text": {
- "name": "Text",
- "description": "stylable block of text",
- "props": {
- "text": "string",
- "type": {
- "type": "string",
- "default": "none"
- }
- },
- "tags": [
- "div",
- "container"
- ]
- },
- "richtext": {
- "name": "Rich Text",
- "description": "A component that allows the user to enter long form text.",
- "props": {
- "value": "string"
- }
- },
- "icon": {
- "description": "A HTML icon tag",
- "props": {
- "icon": "string",
- "size": {
- "type": "string",
- "default": "md"
- },
- "color": {
- "type": "string",
- "default": "#000"
- }
- }
- },
- "datagrid": {
- "name": "Grid",
- "description": "a datagrid component with functionality to add, remove and edit rows.",
- "data": true,
- "props": {
- "datasource": "tables",
- "editable": "bool",
- "theme": {
- "type": "options",
- "default": "alpine",
- "options": [
- "alpine",
- "alpine-dark",
- "balham",
- "balham-dark",
- "material"
- ]
- },
- "height": {
- "type": "number",
- "default": "540"
- },
- "pagination": {
- "type": "bool",
- "default": true
- },
- "detailUrl": "string"
- }
- },
- "dataform": {
- "name": "Form",
- "description": "an HTML table that fetches data from a table or view and displays it.",
- "data": true,
- "props": {}
- },
- "dataformwide": {
- "name": "Form Wide",
- "description": "an HTML table that fetches data from a table or view and displays it.",
- "data": true,
- "props": {}
- },
- "list": {
- "name": "Repeater",
- "description": "A configurable data list that attaches to your backend tables.",
- "context": "datasource",
- "children": true,
- "data": true,
- "props": {
- "datasource": "tables"
- }
- },
- "stackedlist": {
- "name": "Stacked List",
- "description": "A stacked list component for displaying information",
- "props": {
- "imageUrl": "string",
- "heading": "string",
- "text1": "string",
- "text2": "string",
- "text3": "string",
- "destinationUrl": "string"
- }
- },
- "rowdetail": {
- "name": "Row Detail",
- "description": "Loads a row, using an ID in the url",
- "context": "table",
- "children": true,
- "data": true,
- "baseComponent": true,
- "props": {
- "table": "tables"
- }
- },
- "newrow": {
- "name": "New Row",
- "description": "Prepares a new row for creation",
- "context": "table",
- "children": true,
- "data": true,
- "baseComponent": true,
- "props": {
- "table": "tables"
- }
- },
- "card": {
- "name": "Card",
- "props": {
- "imageUrl": "string",
- "heading": "string",
- "description": "string",
- "linkText": "string",
- "linkUrl": "string",
- "linkColor": {
- "type": "string",
- "default": "#000"
- },
- "linkHoverColor": {
- "type": "string",
- "default": "#000"
- },
- "imageHeight": {
- "type": "options",
- "default": "20rem",
- "options": [
- "12rem",
- "16rem",
- "20rem",
- "24rem"
- ]
- },
- "cardWidth": {
- "type": "options",
- "default": "20rem",
- "options": [
- "16rem",
- "20rem",
- "24rem"
- ]
- }
- }
- },
- "cardstat": {
- "name": "Stat Card",
- "props": {
- "title": "string",
- "value": "string",
- "label": "string"
- }
- },
- "cardhorizontal": {
- "name": "Horizontal Card",
- "props": {
- "imageUrl": "string",
- "heading": "string",
- "description": "string",
- "subtext": "string",
- "linkText": "string",
- "linkUrl": "string",
- "linkColor": {
- "type": "string",
- "default": "#000"
- },
- "linkHoverColor": {
- "type": "string",
- "default": "#000"
- },
- "imageWidth": {
- "type": "options",
- "default": "8rem",
- "options": [
- "8rem",
- "12rem",
- "16rem"
- ]
- },
- "cardWidth": {
- "type": "options",
- "default": "32rem",
- "options": [
- "24rem",
- "28rem",
- "32rem",
- "40rem",
- "48rem",
- "60rem",
- "100%"
- ]
- },
- "imageHeight": {
- "type": "options",
- "default": "8rem",
- "options": [
- "8rem",
- "12rem",
- "16rem"
- ]
- }
- }
- },
- "bar": {
- "description": "Bar Chart",
- "data": true,
- "props": {
- "title": "string",
- "datasource": "tables",
- "labelColumn": "string",
- "valueColumns": "string",
- "height": {
- "type": "string",
- "default": "400"
- },
- "width": "string",
- "dataLabels": "bool",
- "animate": {
- "type": "bool",
- "default": true
- },
- "xAxisLabel": "string",
- "yAxisLabel": "string",
- "legend": "bool",
- "stacked": "bool",
- "yAxisUnits": {
- "type": "options",
- "default": "Default",
- "options": [
- "Default", "Thousands", "Millions"
- ]
- },
- "palette": {
- "type": "options",
- "default": "Palette 1",
- "options": [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10"
- ]
- }
- }
- },
- "line": {
- "description": "Line Chart",
- "data": true,
- "props": {
- "title": "string",
- "datasource": "tables",
- "labelColumn": "string",
- "valueColumns": "string",
- "height": {
- "type": "string",
- "default": "400"
- },
- "width": "string",
- "dataLabels": {
- "type": "bool",
- "default": false
- },
- "animate": {
- "type": "bool",
- "default": true
- },
- "xAxisLabel": "string",
- "yAxisLabel": "string",
- "curve": {
- "type": "options",
- "options": [
- "Smooth",
- "Straight",
- "Stepline"
- ],
- "default": "Smooth"
- },
- "legend": "bool",
- "yAxisUnits": {
- "type": "options",
- "default": "Default",
- "options": [
- "Default", "Thousands", "Millions"
- ]
- },
- "palette": {
- "type": "options",
- "default": "Palette 1",
- "options": [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10"
- ]
- }
- }
- },
- "area": {
- "description": "Area Chart",
- "data": true,
- "props": {
- "title": "string",
- "datasource": "tables",
- "labelColumn": "string",
- "valueColumns": "string",
- "height": {
- "type": "string",
- "default": "400"
- },
- "width": "string",
- "dataLabels": {
- "type": "bool",
- "default": false
- },
- "animate": {
- "type": "bool",
- "default": true
- },
- "xAxisLabel": "string",
- "yAxisLabel": "string",
- "curve": {
- "type": "options",
- "options": [
- "Smooth",
- "Straight",
- "Stepline"
- ],
- "default": "Smooth"
- },
- "legend": "bool",
- "stacked": {
- "type": "bool",
- "default": true
- },
- "gradient": "bool",
- "yAxisUnits": {
- "type": "options",
- "default": "Default",
- "options": [
- "Default", "Thousands", "Millions"
- ]
- },
- "palette": {
- "type": "options",
- "default": "Palette 1",
- "options": [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10"
- ]
- }
- }
- },
- "pie": {
- "description": "Pie Chart",
- "data": true,
- "props": {
- "title": "string",
- "datasource": "tables",
- "labelColumn": "string",
- "valueColumn": "string",
- "height": {
- "type": "string",
- "default": "200"
- },
- "width": "string",
- "dataLabels": "bool",
- "animate": {
- "type": "bool",
- "default": true
- },
- "legend": {
- "type": "bool",
- "default": true
- },
- "palette": {
- "type": "options",
- "default": "Palette 1",
- "options": [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10"
- ]
- }
- }
- },
- "donut": {
- "description": "Donut Chart",
- "data": true,
- "props": {
- "title": "string",
- "datasource": "tables",
- "labelColumn": "string",
- "valueColumn": "string",
- "height": {
- "type": "string",
- "default": "200"
- },
- "width": "string",
- "dataLabels": "bool",
- "animate": {
- "type": "bool",
- "default": true
- },
- "legend": {
- "type": "bool",
- "default": true
- },
- "palette": {
- "type": "options",
- "default": "Palette 1",
- "options": [
- "Palette 1",
- "Palette 2",
- "Palette 3",
- "Palette 4",
- "Palette 5",
- "Palette 6",
- "Palette 7",
- "Palette 8",
- "Palette 9",
- "Palette 10"
- ]
- }
- }
- },
- "candlestick": {
- "description": "Candlestick Chart",
- "data": true,
- "props": {
- "title": "string",
- "datasource": "tables",
- "dateColumn": "string",
- "openColumn": "string",
- "closeColumn": "string",
- "highColumn": "string",
- "lowColumn": "string",
- "height": {
- "type": "string",
- "default": "400"
- },
- "width": "string",
- "animate": {
- "type": "bool",
- "default": true
- },
- "xAxisLabel": "string",
- "yAxisLabel": "string",
- "yAxisUnits": {
- "type": "options",
- "default": "Default",
- "options": [
- "Default", "Thousands", "Millions"
- ]
- }
- }
- },
- "datepicker": {
- "name": "Date Picker",
- "description": "Date Picker",
- "bindable": "value",
- "props": {
- "placeholder": "string"
- }
- },
- "link": {
- "name": "Link",
- "description": "an HTML anchor tag",
- "props": {
- "url": "string",
- "openInNewTab": "bool",
- "text": "string"
- }
- },
- "image": {
- "description": "an HTML tag",
- "props": {
- "url": "string"
- }
- },
- "container": {
- "name": "Container",
- "children": true,
- "description": "An element that contains and lays out other elements. e.g.
{#each properties as prop}
onStyleChanged(styleCategory, key, value)}
- props={{ ...excludeProps(prop, ['control', 'label']) }} />
+ onChange={value => onStyleChanged(styleCategory, prop.key, value)}
+ props={getControlProps(prop)} />
{/each}
{/if}
diff --git a/packages/builder/src/components/userInterface/RoleSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/RoleSelect.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/RoleSelect.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/RoleSelect.svelte
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ScreenSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ScreenSelect.svelte
new file mode 100644
index 0000000000..993e49faa6
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ScreenSelect.svelte
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
diff --git a/packages/builder/src/components/userInterface/TableSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableSelect.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/TableSelect.svelte
rename to packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableSelect.svelte
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableViewFieldSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableViewFieldSelect.svelte
new file mode 100644
index 0000000000..0e93c3e73a
--- /dev/null
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/TableViewFieldSelect.svelte
@@ -0,0 +1,23 @@
+
+
+{#if multiselect}
+
+ {#if assetInstance}
+ {#each assetDefinition as def (`${componentInstance._id}-${def.key}`)}
+ onScreenPropChange(def.key, val)} />
+ {/each}
+ {/if}
+
+ {#if showDisplayName}
+
+ {/if}
+
+ {#if settings && settings.length > 0}
+ {#each settings as setting (`${componentInstance._id}-${setting.key}`)}
+ {#if canRenderControl(setting)}
+ onChange(setting.key, val)}
+ props={{ options: setting.options }} />
+ {/if}
+ {/each}
+ {:else}
+
+
+
diff --git a/packages/builder/src/components/userInterface/propertyCategories.js b/packages/builder/src/components/design/PropertiesPanel/componentStyles.js
similarity index 96%
rename from packages/builder/src/components/userInterface/propertyCategories.js
rename to packages/builder/src/components/design/PropertiesPanel/componentStyles.js
index ebaab9bf39..f3cdaad094 100644
--- a/packages/builder/src/components/userInterface/propertyCategories.js
+++ b/packages/builder/src/components/design/PropertiesPanel/componentStyles.js
@@ -1,7 +1,7 @@
-import Input from "./PropertyPanelControls/Input.svelte"
-import OptionSelect from "./OptionSelect.svelte"
-import FlatButtonGroup from "./FlatButtonGroup.svelte"
-import Colorpicker from "@budibase/colorpicker"
+import Input from "./PropertyControls/Input.svelte"
+import OptionSelect from "./PropertyControls/OptionSelect.svelte"
+import FlatButtonGroup from "./PropertyControls/FlatButtonGroup"
+import Colorpicker from "./PropertyControls/ColorPicker.svelte"
export const layout = [
{
@@ -299,42 +299,36 @@ export const size = [
key: "width",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Height",
key: "height",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Min Width",
key: "min-width",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Max Width",
key: "max-width",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Min Height",
key: "min-height",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Max Height",
key: "max-height",
control: Input,
placeholder: "px",
- textAlign: "center",
},
]
@@ -357,28 +351,24 @@ export const position = [
key: "top",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Right",
key: "right",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Bottom",
key: "bottom",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Left",
key: "left",
control: Input,
placeholder: "px",
- textAlign: "center",
},
{
label: "Z-index",
@@ -458,7 +448,6 @@ export const typography = [
{ label: "60px", value: "60px" },
{ label: "72px", value: "72px" },
],
- textAlign: "center",
},
{
label: "Line H",
@@ -478,7 +467,6 @@ export const typography = [
label: "Color",
key: "color",
control: Colorpicker,
- initialValue: "#000",
},
{
label: "align",
@@ -522,7 +510,6 @@ export const background = [
label: "Color",
key: "background",
control: Colorpicker,
- initialValue: "#000",
},
{
label: "Gradient",
@@ -645,7 +632,6 @@ export const border = [
label: "Color",
key: "border-color",
control: Colorpicker,
- initialValue: "#000",
},
{
label: "Style",
@@ -672,7 +658,6 @@ export const effects = [
label: "Opacity",
key: "opacity",
control: OptionSelect,
- textAlign: "center",
options: [
{ label: "Choose option", value: "" },
{ label: "0", value: "0" },
@@ -758,7 +743,6 @@ export const transitions = [
label: "Duration",
key: "transition-duration",
control: OptionSelect,
- textAlign: "center",
placeholder: "sec",
options: [
{ label: "Choose option", value: "" },
@@ -785,7 +769,7 @@ export const transitions = [
},
]
-export const all = {
+export const allStyles = {
layout,
margin,
padding,
@@ -797,13 +781,3 @@ export const all = {
effects,
transitions,
}
-
-export function excludeProps(props, propsToExclude) {
- const modifiedProps = {}
- for (const prop in props) {
- if (!propsToExclude.includes(prop)) {
- modifiedProps[prop] = props[prop]
- }
- }
- return modifiedProps
-}
diff --git a/packages/builder/src/components/userInterface/Feedback/FeedbackIframe.svelte b/packages/builder/src/components/feedback/FeedbackIframe.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/Feedback/FeedbackIframe.svelte
rename to packages/builder/src/components/feedback/FeedbackIframe.svelte
diff --git a/packages/builder/src/components/userInterface/Feedback/FeedbackNavLink.svelte b/packages/builder/src/components/feedback/FeedbackNavLink.svelte
similarity index 100%
rename from packages/builder/src/components/userInterface/Feedback/FeedbackNavLink.svelte
rename to packages/builder/src/components/feedback/FeedbackNavLink.svelte
diff --git a/packages/builder/src/components/integration/QueryParameterBuilder.svelte b/packages/builder/src/components/integration/QueryParameterBuilder.svelte
index cadbfbf873..d7eaa3bec1 100644
--- a/packages/builder/src/components/integration/QueryParameterBuilder.svelte
+++ b/packages/builder/src/components/integration/QueryParameterBuilder.svelte
@@ -1,17 +1,10 @@
-
-
+ This component doesn't have any additional settings.
+
+ {/if}
+
-
-
-
- {#if parameters.tableId}
-
- {/if}
-
-
-
diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/DeleteRow.svelte b/packages/builder/src/components/userInterface/EventsEditor/actions/DeleteRow.svelte
deleted file mode 100644
index 287f93f835..0000000000
--- a/packages/builder/src/components/userInterface/EventsEditor/actions/DeleteRow.svelte
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
- {#if idFields.length === 0}
-
-
-
diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/SaveRow.svelte b/packages/builder/src/components/userInterface/EventsEditor/actions/SaveRow.svelte
deleted file mode 100644
index 5347dc47f5..0000000000
--- a/packages/builder/src/components/userInterface/EventsEditor/actions/SaveRow.svelte
+++ /dev/null
@@ -1,136 +0,0 @@
-
-
-
- Delete row can only be used within a component that provides data, such as
- a List
-
- {:else}
-
-
- {/if}
-
- {#if idFields.length === 0}
-
- {/if}
-
-
-
diff --git a/packages/builder/src/components/userInterface/EventsEditor/actions/UpdateRow.svelte b/packages/builder/src/components/userInterface/EventsEditor/actions/UpdateRow.svelte
deleted file mode 100644
index 4630adfb2a..0000000000
--- a/packages/builder/src/components/userInterface/EventsEditor/actions/UpdateRow.svelte
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
- Update row can only be used within a component that provides data, such as
- a List
-
- {:else}
-
-
- {/if}
-
- {#if parameters.contextPath}
-
- {#if idFields.length === 0}
-
- {/if}
-
-
-
diff --git a/packages/builder/src/components/userInterface/LayoutTemplateControls.svelte b/packages/builder/src/components/userInterface/LayoutTemplateControls.svelte
deleted file mode 100644
index 619b6a11d3..0000000000
--- a/packages/builder/src/components/userInterface/LayoutTemplateControls.svelte
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
- Update row can only be used within a component that provides data, such as
- a List
-
- {:else}
-
-
- {/if}
-
- {#if rowId}
-
- {#each meta as { placeholder }, i}
- {#each propertyChoices as [displayName, [cssPropValue, icon]]}
-
- {/each}
- {/each}
-
-
-
diff --git a/packages/builder/src/components/userInterface/ScreenSelect.svelte b/packages/builder/src/components/userInterface/ScreenSelect.svelte
deleted file mode 100644
index a1f9f76f20..0000000000
--- a/packages/builder/src/components/userInterface/ScreenSelect.svelte
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
-
-
-
diff --git a/packages/builder/src/components/userInterface/SettingsView.svelte b/packages/builder/src/components/userInterface/SettingsView.svelte
deleted file mode 100644
index 211e04d009..0000000000
--- a/packages/builder/src/components/userInterface/SettingsView.svelte
+++ /dev/null
@@ -1,163 +0,0 @@
-
-
-
- {#if assetInstance}
- {#each assetDefinition as def}
-
- {/each}
- {/if}
-
- {#if displayNameField}
-
- {#if duplicateName}
- Name must be unique
- {/if}
- {/if}
-
- {#if !isLayout && panelDefinition && panelDefinition.length > 0}
- {#each panelDefinition as definition}
- {#if canRenderControl(definition.key, definition.dependsOn)}
-
- {/if}
- {/each}
- {:else}
-
-
-
diff --git a/packages/builder/src/components/userInterface/TableViewFieldSelect.svelte b/packages/builder/src/components/userInterface/TableViewFieldSelect.svelte
deleted file mode 100644
index 0b4b000488..0000000000
--- a/packages/builder/src/components/userInterface/TableViewFieldSelect.svelte
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-{#if multiselect}
-
- This component doesn't have any additional settings.
-
- {/if}
-
-
+
{/if}
, etc",
- "props": {
- "type": {
- "type": "options",
- "options": [
- "article",
- "aside",
- "details",
- "div",
- "firgure",
- "figcaption",
- "footer",
- "header",
- "main",
- "mark",
- "nav",
- "paragraph",
- "summary"
- ],
- "default": "div"
- }
- },
- "baseComponent": true,
- "tags": [
- "div",
- "container",
- "layout"
- ]
- },
- "heading": {
- "name": "Heading",
- "description": "An HTML H1 - H6 tag",
- "props": {
- "text": "string",
- "type": {
- "type": "options",
- "default": "h1",
- "options": [
- "h1",
- "h2",
- "h3",
- "h4",
- "h5",
- "h6"
- ]
- }
- },
- "tags": []
- }
-}
diff --git a/packages/standard-components/manifest.json b/packages/standard-components/manifest.json
new file mode 100644
index 0000000000..901ea0df3c
--- /dev/null
+++ b/packages/standard-components/manifest.json
@@ -0,0 +1,1106 @@
+{
+ "container": {
+ "name": "Container",
+ "description": "This component contains things within itself",
+ "icon": "ri-layout-column-line",
+ "hasChildren": true,
+ "styleable": true,
+ "settings": [
+ {
+ "type": "select",
+ "key": "type",
+ "label": "Type",
+ "defaultValue": "div",
+ "options": [
+ "article",
+ "aside",
+ "details",
+ "div",
+ "figure",
+ "figcaption",
+ "footer",
+ "header",
+ "main",
+ "mark",
+ "nav",
+ "paragraph",
+ "summary"
+ ]
+ }
+ ]
+ },
+ "datagrid": {
+ "name": "Grid",
+ "description": "A datagrid component with functionality to add, remove and edit rows.",
+ "icon": "ri-grid-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "datasource",
+ "label": "Source",
+ "key": "datasource"
+ },
+ {
+ "type": "detailScreen",
+ "label": "Detail URL",
+ "key": "detailUrl"
+ },
+ {
+ "type": "boolean",
+ "label": "Editable",
+ "key": "editable"
+ },
+ {
+ "type": "select",
+ "label": "Theme",
+ "key": "theme",
+ "options": ["alpine", "alpine-dark", "balham", "balham-dark", "material"],
+ "defaultValue": "alpine"
+ },
+ {
+ "type": "number",
+ "label": "Height",
+ "key": "height",
+ "defaultValue": "500"
+ },
+ {
+ "type": "boolean",
+ "label": "Pagination",
+ "key": "pagination"
+ }
+ ]
+ },
+ "screenslot": {
+ "name": "Screenslot",
+ "icon": "ri-artboard-2-line",
+ "description": "Contains your app screens",
+ "styleable": true
+ },
+ "button": {
+ "name": "Button",
+ "description": "A basic html button that is ready for styling",
+ "icon": "ri-share-box-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Text",
+ "key": "text"
+ },
+ {
+ "type": "boolean",
+ "label": "Disabled",
+ "key": "disabled"
+ },
+ {
+ "type": "event",
+ "label": "On Click",
+ "key": "onClick"
+ }
+ ]
+ },
+ "list": {
+ "name": "Repeater",
+ "description": "A configurable data list that attaches to your backend tables.",
+ "icon": "ri-list-check-2",
+ "styleable": true,
+ "hasChildren": true,
+ "dataProvider": true,
+ "datasourceSetting": "datasource",
+ "settings": [
+ {
+ "type": "datasource",
+ "label": "Data",
+ "key": "datasource"
+ }
+ ]
+ },
+ "dataform": {
+ "name": "Form",
+ "icon": "ri-file-edit-line",
+ "styleable": true
+ },
+ "dataformwide": {
+ "name": "Wide Form",
+ "icon": "ri-file-edit-line",
+ "styleable": true
+ },
+ "input": {
+ "name": "Text Field",
+ "description": "A textfield component that allows the user to input text.",
+ "icon": "ri-edit-box-line",
+ "styleable": true,
+ "bindable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Label",
+ "key": "label"
+ },
+ {
+ "label": "Type",
+ "key": "type",
+ "defaultValue": "text",
+ "options": ["text", "password"]
+ }
+ ]
+ },
+ "richtext": {
+ "name": "Rich Text",
+ "description": "A component that allows the user to enter long form text.",
+ "icon": "ri-edit-box-line",
+ "styleable": true,
+ "bindable": true
+ },
+ "datepicker": {
+ "name": "Date Picker",
+ "description": "A basic date picker component",
+ "icon": "ri-calendar-line",
+ "styleable": true,
+ "bindable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Placeholder",
+ "key": "placeholder"
+ }
+ ]
+ },
+ "stackedlist": {
+ "name": "Stacked List",
+ "icon": "ri-archive-drawer-line",
+ "description": "A basic card component that can contain content and actions.",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Image",
+ "key": "imageUrl"
+ },
+ {
+ "type": "text",
+ "label": "Heading",
+ "key": "heading"
+ },
+ {
+ "type": "text",
+ "label": "Text 1",
+ "key": "text1"
+ },
+ {
+ "type": "text",
+ "label": "Text 2",
+ "key": "text2"
+ },
+ {
+ "type": "text",
+ "label": "Text 3",
+ "key": "text3"
+ },
+ {
+ "type": "screen",
+ "label": "Link URL",
+ "key": "destinationUrl"
+ }
+ ]
+ },
+ "card": {
+ "name": "Vertical Card",
+ "description": "A basic card component that can contain content and actions.",
+ "icon": "ri-layout-column-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Image",
+ "key": "imageUrl"
+ },
+ {
+ "type": "text",
+ "label": "Heading",
+ "key": "heading"
+ },
+ {
+ "type": "text",
+ "label": "Description",
+ "key": "description"
+ },
+ {
+ "type": "text",
+ "label": "Link Text",
+ "key": "linkText"
+ },
+ {
+ "type": "screen",
+ "label": "Link Url",
+ "key": "linkUrl"
+ },
+ {
+ "type": "color",
+ "label": "Link Color",
+ "key": "linkColor",
+ "defaultValue": "#000"
+ },
+ {
+ "type": "color",
+ "label": "Hover Color",
+ "key": "linkHoverColor",
+ "defaultValue": "#222"
+ },
+ {
+ "type": "select",
+ "label": "Image Height",
+ "key": "imageHeight",
+ "options": ["auto", "12rem", "16rem", "20rem", "24rem"],
+ "defaultValue": "auto"
+ },
+ {
+ "type": "select",
+ "label": "Card Width",
+ "key": "cardWidth",
+ "options": ["16rem", "20rem", "24rem"],
+ "defaultValue": "20rem"
+ }
+ ]
+ },
+ "text": {
+ "name": "Paragraph",
+ "description": "A component for displaying paragraph text.",
+ "icon": "ri-paragraph",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Text",
+ "key": "text"
+ }
+ ]
+ },
+ "heading": {
+ "name": "Headline",
+ "icon": "ri-heading",
+ "description": "A component for displaying heading text",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "key": "text",
+ "label": "Text"
+ },
+ {
+ "type": "select",
+ "key": "type",
+ "label": "Type",
+ "options": ["h1", "h2", "h3", "h4", "h5", "h6"],
+ "defaultValue": "h1"
+ }
+ ]
+ },
+ "image": {
+ "name": "Image",
+ "description": "A basic component for displaying images",
+ "icon": "ri-image-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "URL",
+ "key": "url"
+ }
+ ]
+ },
+ "icon": {
+ "name": "Icon",
+ "description": "A basic component for displaying icons",
+ "icon": "ri-sun-fill",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "icon",
+ "label": "Icon",
+ "key": "icon"
+ },
+ {
+ "type": "select",
+ "label": "Size",
+ "key": "size",
+ "defaultValue": "md",
+ "options": [
+ { "value": "ri-xxs", "label": "xxs" },
+ { "value": "ri-xs", "label": "xs" },
+ { "value": "ri-sm", "label": "sm" },
+ { "value": "ri-1x", "label": "md" },
+ { "value": "ri-lg", "label": "lg" },
+ { "value": "ri-xl", "label": "xl" },
+ { "value": "ri-2x", "label": "2x" },
+ { "value": "ri-3x", "label": "3x" },
+ { "value": "ri-4x", "label": "4x" },
+ { "value": "ri-5x", "label": "5x" },
+ { "value": "ri-6x", "label": "6x" },
+ { "value": "ri-7x", "label": "7x" },
+ { "value": "ri-8x", "label": "8x" },
+ { "value": "ri-9x", "label": "9x" },
+ { "value": "ri-10x", "label": "10x" }
+ ]
+ },
+ {
+ "type": "color",
+ "label": "Color",
+ "key": "color",
+ "defaultValue": "#000"
+ }
+ ]
+ },
+ "login": {
+ "name": "Login Form",
+ "description": "A component that automatically generates a login screen for your app.",
+ "icon": "ri-login-box-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Logo",
+ "key": "logo"
+ },
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title"
+ },
+ {
+ "type": "text",
+ "label": "Button Text",
+ "key": "buttonText"
+ }
+ ]
+ },
+ "navigation": {
+ "name": "Nav Bar",
+ "description": "A component for handling the navigation within your app.",
+ "icon": "ri-navigation-line",
+ "styleable": true,
+ "hasChildren": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Logo URL",
+ "key": "logoUrl"
+ }
+ ]
+ },
+ "link": {
+ "name": "Link",
+ "description": "A basic link component for internal and external links",
+ "icon": "ri-link",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Text",
+ "key": "text"
+ },
+ {
+ "type": "screen",
+ "label": "URL",
+ "key": "url"
+ },
+ {
+ "type": "boolean",
+ "label": "New Tab",
+ "key": "openInNewTab"
+ }
+ ]
+ },
+ "rowdetail": {
+ "name": "Row Detail",
+ "description": "Loads a row, using an id from the URL, which can be used with {{ context }}, in children",
+ "icon": "ri-profile-line",
+ "styleable": true,
+ "hasChildren": true,
+ "dataProvider": true,
+ "datasourceSetting": "table",
+ "settings": [
+ {
+ "type": "table",
+ "label": "Table",
+ "key": "table"
+ }
+ ]
+ },
+ "newrow": {
+ "name": "New Row",
+ "description": "Sets up a new row for creation, which can be used with {{ context }}, in children",
+ "icon": "ri-profile-line",
+ "hasChildren": true,
+ "styleable": true,
+ "dataProvider": true,
+ "datasourceSetting": "table",
+ "settings": [
+ {
+ "type": "table",
+ "label": "Table",
+ "key": "table"
+ }
+ ]
+ },
+ "cardhorizontal": {
+ "name": "Horizontal Card",
+ "description": "A basic card component that can contain content and actions.",
+ "icon": "ri-layout-row-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Image",
+ "key": "imageUrl"
+ },
+ {
+ "type": "text",
+ "label": "Heading",
+ "key": "heading"
+ },
+ {
+ "type": "text",
+ "label": "Description",
+ "key": "description"
+ },
+ {
+ "type": "text",
+ "label": "Subtext",
+ "key": "subtext"
+ },
+ {
+ "type": "text",
+ "label": "Link Text",
+ "key": "linkText"
+ },
+ {
+ "type": "screen",
+ "label": "Link URL",
+ "key": "linkUrl"
+ },
+ {
+ "type": "color",
+ "label": "Link Color",
+ "key": "linkColor",
+ "defaultValue": "#000"
+ },
+ {
+ "type": "color",
+ "label": "Hover Color",
+ "key": "linkHoverColor",
+ "defaultValue": "#222"
+ },
+ {
+ "type": "select",
+ "label": "Card Width",
+ "key": "cardWidth",
+ "options": ["24rem", "28rem", "32rem", "40rem", "48rem", "60rem", "100%"],
+ "defaultValue": "32rem"
+ },
+ {
+ "type": "select",
+ "label": "Image Width",
+ "key": "imageWidth",
+ "options": ["auto", "8rem", "12rem", "16rem"],
+ "defaultValue": "8rem"
+ },
+ {
+ "type": "select",
+ "label": "Image Height",
+ "key": "imageHeight",
+ "options": ["auto", "8rem", "12rem", "16rem", "auto"],
+ "defaultValue": "auto"
+ }
+ ]
+ },
+ "cardstat": {
+ "name": "Stat Card",
+ "description": "A card component for displaying numbers.",
+ "icon": "ri-dual-sim-2-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title",
+ "placeholder": "Total Revenue"
+ },
+ {
+ "type": "text",
+ "label": "Value",
+ "key": "value",
+ "placeholder": "$1,981,983"
+ },
+ {
+ "type": "text",
+ "label": "Label",
+ "key": "label",
+ "placeholder": "Stripe"
+ }
+ ]
+ },
+ "embed": {
+ "name": "Embed",
+ "icon": "ri-code-line",
+ "description": "Embed content from 3rd party sources",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Embed",
+ "key": "embed"
+ }
+ ]
+ },
+ "bar": {
+ "name": "Bar Chart",
+ "description": "Bar chart",
+ "icon": "ri-bar-chart-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title"
+ },
+ {
+ "type": "datasource",
+ "label": "Data",
+ "key": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Label Col.",
+ "key": "labelColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "multifield",
+ "label": "Data Cols.",
+ "key": "valueColumns",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "select",
+ "label": "Format",
+ "key": "yAxisUnits",
+ "options": ["Default", "Thousands", "Millions"],
+ "defaultValue": "Default"
+ },
+ {
+ "type": "text",
+ "label": "Y Axis Label",
+ "key": "yAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "X Axis Label",
+ "key": "xAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "Width",
+ "key": "width"
+ },
+ {
+ "type": "text",
+ "label": "Height",
+ "key": "height",
+ "defaultValue": "400"
+ },
+ {
+ "type": "select",
+ "label": "Colours",
+ "key": "palette",
+ "defaultValue": "Palette 1",
+ "options": [
+ "Palette 1",
+ "Palette 2",
+ "Palette 3",
+ "Palette 4",
+ "Palette 5",
+ "Palette 6",
+ "Palette 7",
+ "Palette 8",
+ "Palette 9",
+ "Palette 10"
+ ]
+ },
+ {
+ "type": "boolean",
+ "label": "Stacked",
+ "key": "stacked",
+ "defaultValue": false
+ },
+ {
+ "type": "boolean",
+ "label": "Data Labels",
+ "key": "dataLabels",
+ "defaultValue": false
+ },
+ {
+ "type": "boolean",
+ "label": "Animate",
+ "key": "animate",
+ "defaultValue": true
+ },
+ {
+ "type": "boolean",
+ "label": "Legend",
+ "key": "legend",
+ "defaultValue": false
+ }
+ ]
+ },
+ "line": {
+ "name": "Line Chart",
+ "description": "Line chart",
+ "icon": "ri-line-chart-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title"
+ },
+ {
+ "type": "datasource",
+ "label": "Data",
+ "key": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Label Col.",
+ "key": "labelColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "multifield",
+ "label": "Data Cols.",
+ "key": "valueColumns",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "select",
+ "label": "Format",
+ "key": "yAxisUnits",
+ "options": ["Default", "Thousands", "Millions"],
+ "defaultValue": "Default"
+ },
+ {
+ "type": "text",
+ "label": "Y Axis Label",
+ "key": "yAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "X Axis Label",
+ "key": "xAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "Width",
+ "key": "width"
+ },
+ {
+ "type": "text",
+ "label": "Height",
+ "key": "height",
+ "defaultValue": "400"
+ },
+ {
+ "type": "select",
+ "label": "Colours",
+ "key": "palette",
+ "defaultValue": "Palette 1",
+ "options": [
+ "Palette 1",
+ "Palette 2",
+ "Palette 3",
+ "Palette 4",
+ "Palette 5",
+ "Palette 6",
+ "Palette 7",
+ "Palette 8",
+ "Palette 9",
+ "Palette 10"
+ ]
+ },
+ {
+ "type": "select",
+ "label": "Curve",
+ "key": "curve",
+ "options": ["Smooth", "Straight", "Stepline"],
+ "defaultValue": "Smooth"
+ },
+ {
+ "type": "boolean",
+ "label": "Data Labels",
+ "key": "dataLabels",
+ "defaultValue": false
+ },
+ {
+ "type": "boolean",
+ "label": "Animate",
+ "key": "animate",
+ "defaultValue": true
+ },
+ {
+ "type": "boolean",
+ "label": "Legend",
+ "key": "legend",
+ "defaultValue": false
+ }
+ ]
+ },
+ "area": {
+ "name": "Area Chart",
+ "description": "Line chart",
+ "icon": "ri-line-chart-fill",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title"
+ },
+ {
+ "type": "datasource",
+ "label": "Data",
+ "key": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Label Col.",
+ "key": "labelColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "multifield",
+ "label": "Data Cols.",
+ "key": "valueColumns",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "select",
+ "label": "Format",
+ "key": "yAxisUnits",
+ "options": ["Default", "Thousands", "Millions"],
+ "defaultValue": "Default"
+ },
+ {
+ "type": "text",
+ "label": "Y Axis Label",
+ "key": "yAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "X Axis Label",
+ "key": "xAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "Width",
+ "key": "width"
+ },
+ {
+ "type": "text",
+ "label": "Height",
+ "key": "height",
+ "defaultValue": "400"
+ },
+ {
+ "type": "select",
+ "label": "Colours",
+ "key": "palette",
+ "defaultValue": "Palette 1",
+ "options": [
+ "Palette 1",
+ "Palette 2",
+ "Palette 3",
+ "Palette 4",
+ "Palette 5",
+ "Palette 6",
+ "Palette 7",
+ "Palette 8",
+ "Palette 9",
+ "Palette 10"
+ ]
+ },
+ {
+ "type": "select",
+ "label": "Curve",
+ "key": "curve",
+ "options": ["Smooth", "Straight", "Stepline"],
+ "defaultValue": "Smooth"
+ },
+ {
+ "type": "boolean",
+ "label": "Data Labels",
+ "key": "dataLabels",
+ "defaultValue": false
+ },
+ {
+ "type": "boolean",
+ "label": "Animate",
+ "key": "animate",
+ "defaultValue": true
+ },
+ {
+ "type": "boolean",
+ "label": "Legend",
+ "key": "legend",
+ "defaultValue": false
+ },
+ {
+ "type": "boolean",
+ "label": "Stacked",
+ "key": "stacked",
+ "defaultValue": true
+ },
+ {
+ "type": "boolean",
+ "label": "Gradient",
+ "key": "gradient",
+ "defaultValue": false
+ }
+ ]
+ },
+ "pie": {
+ "name": "Pie Chart",
+ "description": "Pie chart",
+ "icon": "ri-pie-chart-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title"
+ },
+ {
+ "type": "datasource",
+ "label": "Data",
+ "key": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Label Col.",
+ "key": "labelColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Data Col.",
+ "key": "valueColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "text",
+ "label": "Width",
+ "key": "width"
+ },
+ {
+ "type": "text",
+ "label": "Height",
+ "key": "height",
+ "defaultValue": "400"
+ },
+ {
+ "type": "select",
+ "label": "Colours",
+ "key": "palette",
+ "defaultValue": "Palette 1",
+ "options": [
+ "Palette 1",
+ "Palette 2",
+ "Palette 3",
+ "Palette 4",
+ "Palette 5",
+ "Palette 6",
+ "Palette 7",
+ "Palette 8",
+ "Palette 9",
+ "Palette 10"
+ ]
+ },
+ {
+ "type": "boolean",
+ "label": "Data Labels",
+ "key": "dataLabels",
+ "defaultValue": false
+ },
+ {
+ "type": "boolean",
+ "label": "Animate",
+ "key": "animate",
+ "defaultValue": true
+ },
+ {
+ "type": "boolean",
+ "label": "Legend",
+ "key": "legend",
+ "defaultValue": false
+ }
+ ]
+ },
+ "donut": {
+ "name": "Donut Chart",
+ "description": "Donut chart",
+ "icon": "ri-donut-chart-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title"
+ },
+ {
+ "type": "datasource",
+ "label": "Data",
+ "key": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Label Col.",
+ "key": "labelColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Data Col.",
+ "key": "valueColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "text",
+ "label": "Width",
+ "key": "width"
+ },
+ {
+ "type": "text",
+ "label": "Height",
+ "key": "height",
+ "defaultValue": "400"
+ },
+ {
+ "type": "select",
+ "label": "Colours",
+ "key": "palette",
+ "defaultValue": "Palette 1",
+ "options": [
+ "Palette 1",
+ "Palette 2",
+ "Palette 3",
+ "Palette 4",
+ "Palette 5",
+ "Palette 6",
+ "Palette 7",
+ "Palette 8",
+ "Palette 9",
+ "Palette 10"
+ ]
+ },
+ {
+ "type": "boolean",
+ "label": "Data Labels",
+ "key": "dataLabels",
+ "defaultValue": false
+ },
+ {
+ "type": "boolean",
+ "label": "Animate",
+ "key": "animate",
+ "defaultValue": true
+ },
+ {
+ "type": "boolean",
+ "label": "Legend",
+ "key": "legend",
+ "defaultValue": false
+ }
+ ]
+ },
+ "candlestick": {
+ "name": "Candlestick Chart",
+ "description": "Candlestick chart",
+ "icon": "ri-stock-line",
+ "styleable": true,
+ "settings": [
+ {
+ "type": "text",
+ "label": "Title",
+ "key": "title"
+ },
+ {
+ "type": "datasource",
+ "label": "Data",
+ "key": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Date Col.",
+ "key": "dateColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Open Col.",
+ "key": "openColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Close Col.",
+ "key": "closeColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "High Col.",
+ "key": "highColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "field",
+ "label": "Low Col.",
+ "key": "lowColumn",
+ "dependsOn": "datasource"
+ },
+ {
+ "type": "select",
+ "label": "Format",
+ "key": "yAxisUnits",
+ "options": ["Default", "Thousands", "Millions"],
+ "defaultValue": "Default"
+ },
+ {
+ "type": "text",
+ "label": "Y Axis Label",
+ "key": "yAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "X Axis Label",
+ "key": "xAxisLabel"
+ },
+ {
+ "type": "text",
+ "label": "Width",
+ "key": "width"
+ },
+ {
+ "type": "text",
+ "label": "Height",
+ "key": "height",
+ "defaultValue": "400"
+ },
+ {
+ "type": "boolean",
+ "label": "Animate",
+ "key": "animate",
+ "defaultValue": true
+ }
+ ]
+ }
+}
diff --git a/packages/standard-components/src/Button.svelte b/packages/standard-components/src/Button.svelte
index e2a98bb74d..7ce4256844 100644
--- a/packages/standard-components/src/Button.svelte
+++ b/packages/standard-components/src/Button.svelte
@@ -6,7 +6,7 @@
export let className = "default"
export let disabled = false
- export let text
+ export let text = ""
export let onClick
@@ -15,7 +15,7 @@
disabled={disabled || false}
use:styleable={$component.styles}
on:click={onClick}>
- {text}
+ {text || ''}
diff --git a/packages/standard-components/src/ScreenSlotPlaceholder.svelte b/packages/standard-components/src/ScreenSlotPlaceholder.svelte
deleted file mode 100644
index 82e8b28c0e..0000000000
--- a/packages/standard-components/src/ScreenSlotPlaceholder.svelte
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
- This box is just a placeholder, to show you the position of screens. - -
-
-
diff --git a/packages/standard-components/src/charts/BarChart.svelte b/packages/standard-components/src/charts/BarChart.svelte
index 4bf01b9a21..51bc91046e 100644
--- a/packages/standard-components/src/charts/BarChart.svelte
+++ b/packages/standard-components/src/charts/BarChart.svelte
@@ -35,7 +35,7 @@
// Fetch, filter and sort data
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
- const result = await API.fetchDatasource(datasource, $dataContext)
+ const result = await API.fetchDatasource(datasource)
const reducer = row => (valid, column) => valid && row[column] != null
const hasAllColumns = row => allCols.reduce(reducer(row), true)
const data = result
diff --git a/packages/standard-components/src/charts/CandleStickChart.svelte b/packages/standard-components/src/charts/CandleStickChart.svelte
index 341b1d714f..fbad22feaf 100644
--- a/packages/standard-components/src/charts/CandleStickChart.svelte
+++ b/packages/standard-components/src/charts/CandleStickChart.svelte
@@ -33,7 +33,7 @@
// Fetch, filter and sort data
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
- const result = await API.fetchDatasource(datasource, $dataContext)
+ const result = await API.fetchDatasource(datasource)
const reducer = row => (valid, column) => valid && row[column] != null
const hasAllColumns = row => allCols.reduce(reducer(row), true)
const data = result
diff --git a/packages/standard-components/src/charts/LineChart.svelte b/packages/standard-components/src/charts/LineChart.svelte
index 6e7f7f65f0..256ec70fe6 100644
--- a/packages/standard-components/src/charts/LineChart.svelte
+++ b/packages/standard-components/src/charts/LineChart.svelte
@@ -41,7 +41,7 @@
// Fetch, filter and sort data
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
- const result = await API.fetchDatasource(datasource, $dataContext)
+ const result = await API.fetchDatasource(datasource)
const reducer = row => (valid, column) => valid && row[column] != null
const hasAllColumns = row => allCols.reduce(reducer(row), true)
const data = result
diff --git a/packages/standard-components/src/charts/PieChart.svelte b/packages/standard-components/src/charts/PieChart.svelte
index 9a8db6b17a..65ac8ac490 100644
--- a/packages/standard-components/src/charts/PieChart.svelte
+++ b/packages/standard-components/src/charts/PieChart.svelte
@@ -31,7 +31,7 @@
// Fetch, filter and sort data
const schema = (await API.fetchTableDefinition(datasource.tableId)).schema
- const result = await API.fetchDatasource(datasource, $dataContext)
+ const result = await API.fetchDatasource(datasource)
const data = result
.filter(row => row[labelColumn] != null && row[valueColumn] != null)
.slice(0, 20)
diff --git a/packages/standard-components/src/grid/Component.svelte b/packages/standard-components/src/grid/Component.svelte
index 0d1380d8a7..3492301082 100644
--- a/packages/standard-components/src/grid/Component.svelte
+++ b/packages/standard-components/src/grid/Component.svelte
@@ -3,7 +3,7 @@
import { number } from "./valueSetters"
import { getRenderer } from "./customRenderer"
import { isEmpty } from "lodash/fp"
- import { getContext, onMount } from "svelte"
+ import { getContext } from "svelte"
import AgGrid from "@budibase/svelte-ag-grid"
import {
TextButton as DeleteButton,
@@ -34,6 +34,7 @@
["--grid-height"]: `${height}px`,
},
}
+ $: fetchData(datasource)
// These can never change at runtime so don't need to be reactive
let canEdit = editable && datasource && datasource.type !== "view"
@@ -57,8 +58,11 @@
pagination,
}
- async function fetchData() {
- data = await API.fetchDatasource(datasource, $dataContext)
+ async function fetchData(datasource) {
+ if (isEmpty(datasource)) {
+ return
+ }
+ data = await API.fetchDatasource(datasource)
let schema
@@ -115,12 +119,6 @@
dataLoaded = true
}
- $: datasource && fetchData()
-
- onMount(() => {
- if (!isEmpty(datasource)) fetchData()
- })
-
const shouldHideField = name => {
if (name.startsWith("_")) return true
// always 'row'
diff --git a/packages/standard-components/src/index.js b/packages/standard-components/src/index.js
index 65b0fdd3c0..a856e60a14 100644
--- a/packages/standard-components/src/index.js
+++ b/packages/standard-components/src/index.js
@@ -2,27 +2,27 @@ import "@budibase/bbui/dist/bbui.css"
import "flatpickr/dist/flatpickr.css"
export { default as container } from "./Container.svelte"
-export { default as text } from "./Text.svelte"
-export { default as heading } from "./Heading.svelte"
+export { default as datagrid } from "./grid/Component.svelte"
+export { default as screenslot } from "./ScreenSlot.svelte"
+export { default as button } from "./Button.svelte"
export { default as input } from "./Input.svelte"
export { default as richtext } from "./RichText.svelte"
-export { default as button } from "./Button.svelte"
-export { default as login } from "./Login.svelte"
-export { default as link } from "./Link.svelte"
-export { default as image } from "./Image.svelte"
-export { default as navigation } from "./Navigation.svelte"
-export { default as datagrid } from "./grid/Component.svelte"
-export { default as dataform } from "./DataForm.svelte"
-export { default as dataformwide } from "./DataFormWide.svelte"
export { default as list } from "./List.svelte"
-export { default as embed } from "./Embed.svelte"
export { default as stackedlist } from "./StackedList.svelte"
export { default as card } from "./Card.svelte"
+export { default as dataform } from "./DataForm.svelte"
+export { default as dataformwide } from "./DataFormWide.svelte"
+export { default as datepicker } from "./DatePicker.svelte"
+export { default as text } from "./Text.svelte"
+export { default as login } from "./Login.svelte"
+export { default as navigation } from "./Navigation.svelte"
+export { default as link } from "./Link.svelte"
+export { default as rowdetail } from "./RowDetail.svelte"
+export { default as heading } from "./Heading.svelte"
+export { default as image } from "./Image.svelte"
+export { default as embed } from "./Embed.svelte"
export { default as cardhorizontal } from "./CardHorizontal.svelte"
export { default as cardstat } from "./CardStat.svelte"
-export { default as rowdetail } from "./RowDetail.svelte"
export { default as newrow } from "./NewRow.svelte"
-export { default as datepicker } from "./DatePicker.svelte"
export { default as icon } from "./Icon.svelte"
-export { default as screenslotplaceholder } from "./ScreenSlotPlaceholder.svelte"
export * from "./charts"
diff --git a/packages/string-templates/src/processors/preprocessor.js b/packages/string-templates/src/processors/preprocessor.js
index 131fb522f9..c984d61298 100644
--- a/packages/string-templates/src/processors/preprocessor.js
+++ b/packages/string-templates/src/processors/preprocessor.js
@@ -31,7 +31,8 @@ module.exports.processors = [
statement = swapStrings(statement, startBraceIdx + lastIdx, 1, ".[")
}
lastIdx = startBraceIdx + 1
- startBraceIdx = statement.substring(lastIdx + 1).indexOf("[")
+ const nextBraceIdx = statement.substring(lastIdx + 1).indexOf("[")
+ startBraceIdx = nextBraceIdx > 0 ? lastIdx + 1 + nextBraceIdx : -1
}
return statement
}),
Screen Slot
- - The screens that you create will be displayed inside this box. -- This box is just a placeholder, to show you the position of screens. - -