diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte
index 9ff2a764b7..54241ea1cc 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte
@@ -191,6 +191,9 @@
// Number fields
min: setting.min ?? null,
max: setting.max ?? null,
+
+ // Field select settings
+ explanation: setting.explanation,
}}
{bindings}
{componentBindings}
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/componentStructure.json b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/componentStructure.json
index 0f85d2e3e3..ba6f403d81 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/componentStructure.json
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/componentStructure.json
@@ -71,6 +71,7 @@
"multifieldselect",
"s3upload",
"codescanner",
+ "signaturesinglefield",
"bbreferencesinglefield",
"bbreferencefield"
]
diff --git a/packages/builder/src/stores/builder/app.js b/packages/builder/src/stores/builder/app.js
index 7dfee4daa9..e57a079185 100644
--- a/packages/builder/src/stores/builder/app.js
+++ b/packages/builder/src/stores/builder/app.js
@@ -19,6 +19,7 @@ export const INITIAL_APP_META_STATE = {
showNotificationAction: false,
sidePanel: false,
},
+ typeSupportPresets: {},
features: {
componentValidation: false,
disableUserMetadata: false,
@@ -79,6 +80,13 @@ export class AppMetaStore extends BudiStore {
}))
}
+ syncClientTypeSupportPresets(typeSupportPresets) {
+ this.update(state => ({
+ ...state,
+ typeSupportPresets,
+ }))
+ }
+
async syncAppRoutes() {
const resp = await API.fetchAppRoutes()
this.update(state => ({
diff --git a/packages/builder/src/stores/builder/automations.js b/packages/builder/src/stores/builder/automations.js
index cbe48cef33..ff53dda86b 100644
--- a/packages/builder/src/stores/builder/automations.js
+++ b/packages/builder/src/stores/builder/automations.js
@@ -82,6 +82,7 @@ const automationActions = store => ({
steps: [],
trigger,
},
+ disabled: false,
}
const response = await store.actions.save(automation)
await store.actions.fetch()
@@ -134,6 +135,28 @@ const automationActions = store => ({
})
await store.actions.fetch()
},
+ toggleDisabled: async automationId => {
+ let automation
+ try {
+ automation = store.actions.getDefinition(automationId)
+ if (!automation) {
+ return
+ }
+ automation.disabled = !automation.disabled
+ await store.actions.save(automation)
+ notifications.success(
+ `Automation ${
+ automation.disabled ? "enabled" : "disabled"
+ } successfully`
+ )
+ } catch (error) {
+ notifications.error(
+ `Error ${
+ automation && automation.disabled ? "enabling" : "disabling"
+ } automation`
+ )
+ }
+ },
updateBlockInputs: async (block, data) => {
// Create new modified block
let newBlock = {
diff --git a/packages/builder/src/stores/builder/builder.js b/packages/builder/src/stores/builder/builder.js
index 055498bc91..d002062da9 100644
--- a/packages/builder/src/stores/builder/builder.js
+++ b/packages/builder/src/stores/builder/builder.js
@@ -14,7 +14,6 @@ export const INITIAL_BUILDER_STATE = {
tourKey: null,
tourStepKey: null,
hoveredComponentId: null,
- fonts: null,
}
export class BuilderStore extends BudiStore {
@@ -37,16 +36,6 @@ export class BuilderStore extends BudiStore {
this.websocket
}
- loadFonts(fontFaces) {
- const ff = fontFaces.map(
- fontFace => `${fontFace.family}-${fontFace.weight}`
- )
- this.update(state => ({
- ...state,
- fonts: [...(state.fonts || []), ...ff],
- }))
- }
-
init(app) {
if (!app?.appId) {
console.error("BuilderStore: No appId supplied for websocket")
diff --git a/packages/builder/src/stores/builder/components.js b/packages/builder/src/stores/builder/components.js
index 19a4f41532..8498214313 100644
--- a/packages/builder/src/stores/builder/components.js
+++ b/packages/builder/src/stores/builder/components.js
@@ -108,6 +108,7 @@ export class ComponentStore extends BudiStore {
// Sync client features to app store
appStore.syncClientFeatures(components.features)
+ appStore.syncClientTypeSupportPresets(components?.typeSupportPresets ?? {})
return components
}
diff --git a/packages/builder/src/stores/builder/tests/app.test.js b/packages/builder/src/stores/builder/tests/app.test.js
index e0e5d17ba6..728f472317 100644
--- a/packages/builder/src/stores/builder/tests/app.test.js
+++ b/packages/builder/src/stores/builder/tests/app.test.js
@@ -91,6 +91,14 @@ describe("Application Meta Store", () => {
})
})
+ it("Sync type support information to state", async ctx => {
+ ctx.test.appStore.syncClientTypeSupportPresets({ preset: "information" })
+
+ expect(ctx.test.store.typeSupportPresets).toStrictEqual({
+ preset: "information",
+ })
+ })
+
it("Sync component feature flags to state", async ctx => {
ctx.test.appStore.syncClientFeatures(clientFeaturesResp)
diff --git a/packages/builder/src/stores/builder/tests/component.test.js b/packages/builder/src/stores/builder/tests/component.test.js
index b6c9ca27cd..b8baefc5e6 100644
--- a/packages/builder/src/stores/builder/tests/component.test.js
+++ b/packages/builder/src/stores/builder/tests/component.test.js
@@ -42,6 +42,7 @@ vi.mock("stores/builder", async () => {
update: mockAppStore.update,
set: mockAppStore.set,
syncClientFeatures: vi.fn(),
+ syncClientTypeSupportPresets: vi.fn(),
}
const mockTableStore = writable()
const tables = {
diff --git a/packages/cli/src/environment.ts b/packages/cli/src/environment.ts
index 9d017f99b2..51f6e9b972 100644
--- a/packages/cli/src/environment.ts
+++ b/packages/cli/src/environment.ts
@@ -1,3 +1,4 @@
+process.env.DISABLE_PINO_LOGGER = "1"
process.env.NO_JS = "1"
process.env.JS_BCRYPT = "1"
process.env.DISABLE_JWT_WARNING = "1"
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index 86a6d2b7b3..317ccea974 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -1,5 +1,5 @@
#!/usr/bin/env node
-process.env.DISABLE_PINO_LOGGER = "1"
+// have to import this before anything else
import "./environment"
import { getCommands } from "./options"
import { Command } from "commander"
diff --git a/packages/cli/start.sh b/packages/cli/start.sh
index 9650f0bbfa..ae39f73753 100755
--- a/packages/cli/start.sh
+++ b/packages/cli/start.sh
@@ -1,3 +1,3 @@
#!/bin/bash
dir="$(dirname -- "$(readlink -f "${BASH_SOURCE}")")"
-${dir}/node_modules/ts-node/dist/bin.js ${dir}/src/index.ts $@
+${dir}/../../node_modules/ts-node/dist/bin.js ${dir}/src/index.ts $@
diff --git a/packages/client/manifest.json b/packages/client/manifest.json
index 2fae9c0213..afe17c2a76 100644
--- a/packages/client/manifest.json
+++ b/packages/client/manifest.json
@@ -13,6 +13,42 @@
"sidePanel": true,
"skeletonLoader": true
},
+ "typeSupportPresets": {
+ "numberLike": {
+ "supported": ["number", "boolean"],
+ "partialSupport": [
+ { "type": "longform", "message": "stringAsNumber" },
+ { "type": "string", "message": "stringAsNumber" },
+ { "type": "bigint", "message": "stringAsNumber" },
+ { "type": "options", "message": "stringAsNumber" },
+ { "type": "formula", "message": "stringAsNumber" },
+ { "type": "datetime", "message": "dateAsNumber"}
+ ],
+ "unsupported": [
+ { "type": "json", "message": "jsonPrimitivesOnly" }
+ ]
+ },
+ "stringLike": {
+ "supported": ["string", "number", "bigint", "options", "longform", "boolean", "datetime"],
+ "unsupported": [
+ { "type": "json", "message": "jsonPrimitivesOnly" }
+ ]
+ },
+ "datetimeLike": {
+ "supported": ["datetime"],
+ "partialSupport": [
+ { "type": "longform", "message": "stringAsDate" },
+ { "type": "string", "message": "stringAsDate" },
+ { "type": "options", "message": "stringAsDate" },
+ { "type": "formula", "message": "stringAsDate" },
+ { "type": "bigint", "message": "stringAsDate" },
+ { "type": "number", "message": "numberAsDate"}
+ ],
+ "unsupported": [
+ { "type": "json", "message": "jsonPrimitivesOnly" }
+ ]
+ }
+ },
"layout": {
"name": "Layout",
"description": "This component is specific only to layouts",
@@ -1602,6 +1638,7 @@
]
},
"bar": {
+ "documentationLink": "https://docs.budibase.com/docs/bar-chart",
"name": "Bar Chart",
"description": "Bar chart",
"icon": "GraphBarVertical",
@@ -1626,6 +1663,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -1633,6 +1675,11 @@
"label": "Data columns",
"key": "valueColumns",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -1760,6 +1807,7 @@
]
},
"line": {
+ "documentationLink": "https://docs.budibase.com/docs/line-chart",
"name": "Line Chart",
"description": "Line chart",
"icon": "GraphTrend",
@@ -1784,6 +1832,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -1791,6 +1844,11 @@
"label": "Data columns",
"key": "valueColumns",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -1913,6 +1971,7 @@
]
},
"area": {
+ "documentationLink": "https://docs.budibase.com/docs/area-chart",
"name": "Area Chart",
"description": "Line chart",
"icon": "GraphAreaStacked",
@@ -1937,6 +1996,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -1944,6 +2008,11 @@
"label": "Data columns",
"key": "valueColumns",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2078,6 +2147,7 @@
]
},
"pie": {
+ "documentationLink": "https://docs.budibase.com/docs/pie-donut-chart",
"name": "Pie Chart",
"description": "Pie chart",
"icon": "GraphPie",
@@ -2102,13 +2172,23 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
"type": "field",
- "label": "Data columns",
+ "label": "Data column",
"key": "valueColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2207,6 +2287,7 @@
]
},
"donut": {
+ "documentationLink": "https://docs.budibase.com/docs/pie-donut-chart",
"name": "Donut Chart",
"description": "Donut chart",
"icon": "GraphDonut",
@@ -2231,6 +2312,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -2238,6 +2324,11 @@
"label": "Data columns",
"key": "valueColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2336,6 +2427,7 @@
]
},
"candlestick": {
+ "documentationLink": "https://docs.budibase.com/docs/candlestick-chart",
"name": "Candlestick Chart",
"description": "Candlestick chart",
"icon": "GraphBarVerticalStacked",
@@ -2360,6 +2452,11 @@
"label": "Date column",
"key": "dateColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "datetimeLike"
+ }
+ },
"required": true
},
{
@@ -2367,6 +2464,11 @@
"label": "Open column",
"key": "openColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2374,6 +2476,11 @@
"label": "Close column",
"key": "closeColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2381,6 +2488,11 @@
"label": "High column",
"key": "highColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2388,6 +2500,11 @@
"label": "Low column",
"key": "lowColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2427,6 +2544,7 @@
]
},
"histogram": {
+ "documentationLink": "https://docs.budibase.com/docs/histogram-chart",
"name": "Histogram Chart",
"description": "Histogram chart",
"icon": "Histogram",
@@ -2434,7 +2552,6 @@
"width": 600,
"height": 400
},
- "requiredAncestors": ["dataprovider"],
"settings": [
{
"type": "text",
@@ -2452,6 +2569,11 @@
"label": "Data column",
"key": "valueColumn",
"dependsOn": "dataProvider",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -2746,6 +2868,14 @@
"type": "plainText",
"label": "Label",
"key": "label"
+ },
+ {
+ "type": "number",
+ "label": "Initial width",
+ "key": "width",
+ "placeholder": "Auto",
+ "min": 80,
+ "max": 9999
}
]
},
@@ -4107,6 +4237,55 @@
}
]
},
+ "signaturesinglefield": {
+ "name": "Signature",
+ "icon": "AnnotatePen",
+ "styles": ["size"],
+ "size": {
+ "width": 400,
+ "height": 50
+ },
+ "settings": [
+ {
+ "type": "field/signature_single",
+ "label": "Field",
+ "key": "field",
+ "required": true
+ },
+ {
+ "type": "text",
+ "label": "Label",
+ "key": "label"
+ },
+ {
+ "type": "text",
+ "label": "Help text",
+ "key": "helpText"
+ },
+ {
+ "type": "boolean",
+ "label": "Disabled",
+ "key": "disabled",
+ "defaultValue": false
+ },
+ {
+ "type": "event",
+ "label": "On change",
+ "key": "onChange",
+ "context": [
+ {
+ "label": "Field Value",
+ "key": "value"
+ }
+ ]
+ },
+ {
+ "type": "validation/signature_single",
+ "label": "Validation",
+ "key": "validation"
+ }
+ ]
+ },
"embeddedmap": {
"name": "Embedded Map",
"icon": "Location",
@@ -4372,7 +4551,7 @@
"defaultValue": false
},
{
- "type": "validation/attachment",
+ "type": "validation/attachment_single",
"label": "Validation",
"key": "validation"
},
@@ -5256,6 +5435,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -5263,6 +5447,11 @@
"label": "Data column",
"key": "valueColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
}
]
@@ -5281,6 +5470,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -5288,6 +5482,11 @@
"label": "Data column",
"key": "valueColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
}
]
@@ -5306,6 +5505,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -5313,6 +5517,11 @@
"label": "Data columns",
"key": "valueColumns",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -5360,6 +5569,11 @@
"label": "Value column",
"key": "valueColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -5401,6 +5615,11 @@
"label": "Label column",
"key": "labelColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -5408,6 +5627,11 @@
"label": "Data columns",
"key": "valueColumns",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -5450,6 +5674,11 @@
"label": "Label columns",
"key": "labelColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "stringLike"
+ }
+ },
"required": true
},
{
@@ -5457,6 +5686,11 @@
"label": "Data columns",
"key": "valueColumns",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -5511,6 +5745,11 @@
"label": "Date column",
"key": "dateColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "datetimeLike"
+ }
+ },
"required": true
},
{
@@ -5518,6 +5757,11 @@
"label": "Open column",
"key": "openColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -5525,6 +5769,11 @@
"label": "Close column",
"key": "closeColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -5532,6 +5781,11 @@
"label": "High column",
"key": "highColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
@@ -5539,6 +5793,11 @@
"label": "Low column",
"key": "lowColumn",
"dependsOn": "dataSource",
+ "explanation": {
+ "typeSupport": {
+ "preset": "numberLike"
+ }
+ },
"required": true
},
{
diff --git a/packages/client/package.json b/packages/client/package.json
index 71a9e2e055..68c8ec15b1 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -25,7 +25,7 @@
"@budibase/string-templates": "0.0.0",
"@budibase/types": "0.0.0",
"@spectrum-css/card": "3.0.3",
- "apexcharts": "^3.22.1",
+ "apexcharts": "^3.48.0",
"dayjs": "^1.10.8",
"downloadjs": "1.4.7",
"html5-qrcode": "^2.2.1",
@@ -33,8 +33,8 @@
"sanitize-html": "^2.7.0",
"screenfull": "^6.0.1",
"shortid": "^2.2.15",
- "svelte-apexcharts": "^1.0.2",
- "svelte-spa-router": "^4.0.1"
+ "svelte-spa-router": "^4.0.1",
+ "atrament": "^4.3.0"
},
"devDependencies": {
"@rollup/plugin-alias": "^5.1.0",
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index 378fa64b73..8eacbdf041 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -193,6 +193,9 @@
$: pad = pad || (interactive && hasChildren && inDndPath)
$: $dndIsDragging, (pad = false)
+ $: currentTheme = $context?.device?.theme
+ $: darkMode = !currentTheme?.includes("light")
+
// Update component context
$: store.set({
id,
@@ -222,6 +225,7 @@
parent: id,
ancestors: [...($component?.ancestors ?? []), instance._component],
path: [...($component?.path ?? []), id],
+ darkMode,
})
const initialise = (instance, force = false) => {
@@ -283,10 +287,23 @@
const dependsOnKey = setting.dependsOn.setting || setting.dependsOn
const dependsOnValue = setting.dependsOn.value
const realDependentValue = instance[dependsOnKey]
+
+ const sectionDependsOnKey =
+ setting.sectionDependsOn?.setting || setting.sectionDependsOn
+ const sectionDependsOnValue = setting.sectionDependsOn?.value
+ const sectionRealDependentValue = instance[sectionDependsOnKey]
+
if (dependsOnValue == null && realDependentValue == null) {
return false
}
- if (dependsOnValue !== realDependentValue) {
+ if (dependsOnValue != null && dependsOnValue !== realDependentValue) {
+ return false
+ }
+
+ if (
+ sectionDependsOnValue != null &&
+ sectionDependsOnValue !== sectionRealDependentValue
+ ) {
return false
}
}
diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte
index cf0ec76109..7a07ceb6e1 100644
--- a/packages/client/src/components/app/GridBlock.svelte
+++ b/packages/client/src/components/app/GridBlock.svelte
@@ -37,13 +37,16 @@
let grid
let gridContext
- let minHeight
+ let minHeight = 0
+ $: currentTheme = $context?.device?.theme
+ $: darkMode = !currentTheme?.includes("light")
$: parsedColumns = getParsedColumns(columns)
$: columnWhitelist = parsedColumns.filter(x => x.active).map(x => x.field)
$: schemaOverrides = getSchemaOverrides(parsedColumns)
$: enrichedButtons = enrichButtons(buttons)
$: selectedRows = deriveSelectedRows(gridContext)
+ $: styles = patchStyles($component.styles, minHeight)
$: data = { selectedRows: $selectedRows }
$: actions = [
{
@@ -84,9 +87,11 @@
const getSchemaOverrides = columns => {
let overrides = {}
- columns.forEach(column => {
+ columns.forEach((column, idx) => {
overrides[column.field] = {
displayName: column.label,
+ width: column.width,
+ order: idx,
}
})
return overrides
@@ -128,52 +133,55 @@
)
}
+ const patchStyles = (styles, minHeight) => {
+ return {
+ ...styles,
+ normal: {
+ ...styles?.normal,
+ "min-height": `${minHeight}px`,
+ },
+ }
+ }
+
onMount(() => {
gridContext = grid.getContext()
gridContext.minHeight.subscribe($height => (minHeight = $height))
})
-
-
- onRowClick?.({ row: e.detail })}
- />
-
-
+
+ onRowClick?.({ row: e.detail })}
+ />
+
diff --git a/packages/client/src/components/app/charts/ApexOptionsBuilder.js b/packages/client/src/components/app/charts/ApexOptionsBuilder.js
deleted file mode 100644
index 04b5805df3..0000000000
--- a/packages/client/src/components/app/charts/ApexOptionsBuilder.js
+++ /dev/null
@@ -1,195 +0,0 @@
-export class ApexOptionsBuilder {
- constructor() {
- this.formatters = {
- ["Default"]: val => (isNaN(val) ? val : Math.round(val * 100) / 100),
- ["Thousands"]: val => `${Math.round(val / 1000)}K`,
- ["Millions"]: val => `${Math.round(val / 1000000)}M`,
- }
- this.options = {
- series: [],
- legend: {
- show: false,
- position: "top",
- horizontalAlign: "right",
- showForSingleSeries: true,
- showForNullSeries: true,
- showForZeroSeries: true,
- },
- chart: {
- toolbar: {
- show: false,
- },
- zoom: {
- enabled: false,
- },
- },
- xaxis: {
- labels: {
- formatter: this.formatters.Default,
- },
- },
- yaxis: {
- labels: {
- formatter: this.formatters.Default,
- },
- },
- }
- }
-
- setOption(path, value) {
- if (value == null || value === "") {
- return this
- }
- let tmp = this.options
- for (let i = 0; i < path.length - 1; i++) {
- const step = path[i]
- if (!tmp[step]) {
- tmp[step] = {}
- }
- tmp = tmp[step]
- }
- tmp[path[path.length - 1]] = value
- return this
- }
-
- getOptions() {
- return this.options
- }
-
- type(type) {
- return this.setOption(["chart", "type"], type)
- }
-
- title(title) {
- return this.setOption(["title", "text"], title)
- }
-
- colors(colors) {
- if (!colors) {
- delete this.options.colors
- this.options["customColor"] = false
- return this
- }
- this.options["customColor"] = true
- return this.setOption(["colors"], colors)
- }
-
- width(width) {
- return this.setOption(["chart", "width"], width || undefined)
- }
-
- height(height) {
- return this.setOption(["chart", "height"], height || undefined)
- }
-
- xLabel(label) {
- return this.setOption(["xaxis", "title", "text"], label)
- }
-
- yLabel(label) {
- return this.setOption(["yaxis", "title", "text"], label)
- }
-
- xCategories(categories) {
- return this.setOption(["xaxis", "categories"], categories)
- }
-
- yCategories(categories) {
- return this.setOption(["yaxis", "categories"], categories)
- }
-
- series(series) {
- return this.setOption(["series"], series)
- }
-
- horizontal(horizontal) {
- return this.setOption(["plotOptions", "bar", "horizontal"], horizontal)
- }
-
- dataLabels(dataLabels) {
- return this.setOption(["dataLabels", "enabled"], dataLabels)
- }
-
- animate(animate) {
- return this.setOption(["chart", "animations", "enabled"], animate)
- }
-
- curve(curve) {
- return this.setOption(["stroke", "curve"], curve)
- }
-
- gradient(gradient) {
- const fill = {
- type: "gradient",
- gradient: {
- shadeIntensity: 1,
- opacityFrom: 0.7,
- opacityTo: 0.9,
- stops: [0, 90, 100],
- },
- }
- return this.setOption(["fill"], gradient ? fill : undefined)
- }
-
- legend(legend) {
- return this.setOption(["legend", "show"], legend)
- }
-
- legendPosition(position) {
- return this.setOption(["legend", "position"], position)
- }
-
- stacked(stacked) {
- return this.setOption(["chart", "stacked"], stacked)
- }
-
- labels(labels) {
- return this.setOption(["labels"], labels)
- }
-
- xUnits(units) {
- return this.setOption(
- ["xaxis", "labels", "formatter"],
- this.formatters[units || "Default"]
- )
- }
-
- yUnits(units) {
- return this.setOption(
- ["yaxis", "labels", "formatter"],
- this.formatters[units || "Default"]
- )
- }
-
- clearXFormatter() {
- delete this.options.xaxis.labels
- return this
- }
-
- clearYFormatter() {
- delete this.options.yaxis.labels
- return this
- }
-
- xType(type) {
- return this.setOption(["xaxis", "type"], type)
- }
-
- yType(type) {
- return this.setOption(["yaxis", "type"], type)
- }
-
- yTooltip(yTooltip) {
- return this.setOption(["yaxis", "tooltip", "enabled"], yTooltip)
- }
-
- palette(palette) {
- if (!palette) {
- return this
- }
- return this.setOption(
- ["theme", "palette"],
- palette.toLowerCase().replace(/[\W]/g, "")
- )
- }
-}
diff --git a/packages/client/src/components/app/charts/AreaChart.svelte b/packages/client/src/components/app/charts/AreaChart.svelte
index dc80b2b9da..a9a61e59f6 100644
--- a/packages/client/src/components/app/charts/AreaChart.svelte
+++ b/packages/client/src/components/app/charts/AreaChart.svelte
@@ -1,5 +1,159 @@
-
+
diff --git a/packages/client/src/components/app/charts/BarChart.svelte b/packages/client/src/components/app/charts/BarChart.svelte
index fd8443e2d6..aeebfe9461 100644
--- a/packages/client/src/components/app/charts/BarChart.svelte
+++ b/packages/client/src/components/app/charts/BarChart.svelte
@@ -1,11 +1,12 @@
diff --git a/packages/client/src/components/app/charts/CandleStickChart.svelte b/packages/client/src/components/app/charts/CandleStickChart.svelte
index b2760b005e..61cdef180b 100644
--- a/packages/client/src/components/app/charts/CandleStickChart.svelte
+++ b/packages/client/src/components/app/charts/CandleStickChart.svelte
@@ -1,6 +1,6 @@
diff --git a/packages/client/src/components/app/charts/DonutChart.svelte b/packages/client/src/components/app/charts/DonutChart.svelte
index 721a09053a..dad9edfd67 100644
--- a/packages/client/src/components/app/charts/DonutChart.svelte
+++ b/packages/client/src/components/app/charts/DonutChart.svelte
@@ -1,5 +1,99 @@
-
+
diff --git a/packages/client/src/components/app/charts/HistogramChart.svelte b/packages/client/src/components/app/charts/HistogramChart.svelte
index 26b9028550..37c395d45f 100644
--- a/packages/client/src/components/app/charts/HistogramChart.svelte
+++ b/packages/client/src/components/app/charts/HistogramChart.svelte
@@ -1,135 +1,154 @@
diff --git a/packages/client/src/components/app/charts/LineChart.svelte b/packages/client/src/components/app/charts/LineChart.svelte
index 7f82a833d2..c2dac189e1 100644
--- a/packages/client/src/components/app/charts/LineChart.svelte
+++ b/packages/client/src/components/app/charts/LineChart.svelte
@@ -1,8 +1,7 @@
diff --git a/packages/client/src/components/app/charts/PieChart.svelte b/packages/client/src/components/app/charts/PieChart.svelte
index 8cb7317d94..3250a2ca95 100644
--- a/packages/client/src/components/app/charts/PieChart.svelte
+++ b/packages/client/src/components/app/charts/PieChart.svelte
@@ -1,6 +1,6 @@
diff --git a/packages/client/src/components/app/charts/utils.js b/packages/client/src/components/app/charts/utils.js
new file mode 100644
index 0000000000..1aea22c991
--- /dev/null
+++ b/packages/client/src/components/app/charts/utils.js
@@ -0,0 +1,51 @@
+export const formatters = {
+ ["Default"]: val => val,
+ ["Thousands"]: val => `${Math.round(val / 1000)}K`,
+ ["Millions"]: val => `${Math.round(val / 1000000)}M`,
+ ["Datetime"]: val => new Date(val).toLocaleString(),
+}
+
+export const parsePalette = paletteName => {
+ if (paletteName === "Custom") {
+ // return null in this case so that the palette option doesn't get consumed by Apex Charts
+ return null
+ }
+
+ const [_, number] = paletteName.split(" ")
+
+ return `palette${number}`
+}
+
+// Deep clone which copies function references
+export const cloneDeep = value => {
+ const typesToNaiveCopy = ["string", "boolean", "number", "function", "symbol"]
+
+ if (value === null) {
+ return null
+ }
+
+ if (value === undefined) {
+ return undefined
+ }
+
+ if (typesToNaiveCopy.includes(typeof value)) {
+ return value
+ }
+
+ if (Array.isArray(value)) {
+ return value.map(element => cloneDeep(element))
+ }
+
+ // Only copy "pure" objects, we want to error on stuff like Maps or Sets
+ if (typeof value === "object" && value.constructor.name === "Object") {
+ const cloneObject = {}
+
+ Object.entries(value).forEach(([key, childValue]) => {
+ cloneObject[key] = cloneDeep(childValue)
+ })
+
+ return cloneObject
+ }
+
+ throw `Unsupported value: "${value}" of type: "${typeof value}"`
+}
diff --git a/packages/client/src/components/app/charts/utils.test.js b/packages/client/src/components/app/charts/utils.test.js
new file mode 100644
index 0000000000..1b065e2fae
--- /dev/null
+++ b/packages/client/src/components/app/charts/utils.test.js
@@ -0,0 +1,31 @@
+import { expect, describe, it, vi } from "vitest"
+import { cloneDeep } from "./utils"
+
+describe("utils", () => {
+ let context
+
+ beforeEach(() => {
+ vi.clearAllMocks()
+ context = {}
+ })
+
+ describe("cloneDeep", () => {
+ beforeEach(() => {
+ context.value = {
+ obj: { one: 1, two: 2 },
+ arr: [1, { first: null, second: undefined }, 2],
+ str: "test",
+ num: 123,
+ bool: true,
+ sym: Symbol("test"),
+ func: () => "some value",
+ }
+ context.cloneValue = cloneDeep(context.value)
+ })
+
+ it("to clone the object and not copy object references", () => {
+ expect(context.cloneValue.obj.one).toEqual(1)
+ expect(context.cloneValue.obj.two).toEqual(2)
+ })
+ })
+})
diff --git a/packages/client/src/components/app/forms/SignatureField.svelte b/packages/client/src/components/app/forms/SignatureField.svelte
new file mode 100644
index 0000000000..bdae148368
--- /dev/null
+++ b/packages/client/src/components/app/forms/SignatureField.svelte
@@ -0,0 +1,129 @@
+
+
+
+
+
+ {#if fieldState}
+ {#if (Array.isArray(fieldState?.value) && !fieldState?.value?.length) || !fieldState?.value}
+ {
+ if (!$builderStore.inBuilder) {
+ modal.show()
+ }
+ }}
+ >
+ Add signature
+
+ {:else}
+
+
+
+ {/if}
+ {/if}
+
+
+
diff --git a/packages/client/src/components/app/forms/index.js b/packages/client/src/components/app/forms/index.js
index 15966c3765..391b5fa19f 100644
--- a/packages/client/src/components/app/forms/index.js
+++ b/packages/client/src/components/app/forms/index.js
@@ -16,5 +16,6 @@ export { default as formstep } from "./FormStep.svelte"
export { default as jsonfield } from "./JSONField.svelte"
export { default as s3upload } from "./S3Upload.svelte"
export { default as codescanner } from "./CodeScannerField.svelte"
+export { default as signaturesinglefield } from "./SignatureField.svelte"
export { default as bbreferencefield } from "./BBReferenceField.svelte"
export { default as bbreferencesinglefield } from "./BBReferenceSingleField.svelte"
diff --git a/packages/client/src/components/app/forms/validation.js b/packages/client/src/components/app/forms/validation.js
index bdd7213cb0..46a5330cf3 100644
--- a/packages/client/src/components/app/forms/validation.js
+++ b/packages/client/src/components/app/forms/validation.js
@@ -200,6 +200,17 @@ const parseType = (value, type) => {
return value
}
+ // Parse attachment/signature single, treating no key as null
+ if (
+ type === FieldTypes.ATTACHMENT_SINGLE ||
+ type === FieldTypes.SIGNATURE_SINGLE
+ ) {
+ if (!value?.key) {
+ return null
+ }
+ return value
+ }
+
// Parse links, treating no elements as null
if (type === FieldTypes.LINK) {
if (!Array.isArray(value) || !value.length) {
@@ -246,10 +257,8 @@ const maxLengthHandler = (value, rule) => {
// Evaluates a max file size (MB) constraint
const maxFileSizeHandler = (value, rule) => {
const limit = parseType(rule.value, "number")
- return (
- value == null ||
- !value.some(attachment => attachment.size / 1000000 > limit)
- )
+ const check = attachment => attachment.size / 1000000 > limit
+ return value == null || !(value?.key ? check(value) : value.some(check))
}
// Evaluates a max total upload size (MB) constraint
@@ -257,8 +266,11 @@ const maxUploadSizeHandler = (value, rule) => {
const limit = parseType(rule.value, "number")
return (
value == null ||
- value.reduce((acc, currentItem) => acc + currentItem.size, 0) / 1000000 <=
- limit
+ (value?.key
+ ? value.size / 1000000 <= limit
+ : value.reduce((acc, currentItem) => acc + currentItem.size, 0) /
+ 1000000 <=
+ limit)
)
}
diff --git a/packages/client/src/utils/componentProps.js b/packages/client/src/utils/componentProps.js
index efe69938e7..bdf74c8014 100644
--- a/packages/client/src/utils/componentProps.js
+++ b/packages/client/src/utils/componentProps.js
@@ -108,7 +108,12 @@ export const getSettingsDefinition = definition => {
let settings = []
definition.settings?.forEach(setting => {
if (setting.section) {
- settings = settings.concat(setting.settings || [])
+ settings = settings.concat(
+ (setting.settings || [])?.map(childSetting => ({
+ ...childSetting,
+ sectionDependsOn: setting.dependsOn,
+ }))
+ )
} else {
settings.push(setting)
}
diff --git a/packages/frontend-core/src/components/SignatureModal.svelte b/packages/frontend-core/src/components/SignatureModal.svelte
new file mode 100644
index 0000000000..8132c5bced
--- /dev/null
+++ b/packages/frontend-core/src/components/SignatureModal.svelte
@@ -0,0 +1,59 @@
+
+
+
+ {
+ onConfirm(canvas)
+ }}
+ >
+
+ {title}
+
+
+ {
+ edited = true
+ }}
+ />
+
+
+
+
+
diff --git a/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte b/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte
index ea452c86a8..f485593c46 100644
--- a/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte
@@ -8,7 +8,6 @@
export let onChange
export let readonly = false
export let api
- export let invertX = false
export let schema
export let maximum
@@ -92,13 +91,7 @@