From 8563471aeac7c6b78da7f5fde1427bc2672285d7 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 31 May 2024 16:21:21 +0100 Subject: [PATCH 1/9] Don't update text settings when editing inline unless the value actually changes, to prevent losing HBS or JS expressions --- .../client/src/components/app/Button.svelte | 28 ++++++++++--------- .../client/src/components/app/Heading.svelte | 7 ++++- .../client/src/components/app/Link.svelte | 7 ++++- .../client/src/components/app/Text.svelte | 7 ++++- .../src/components/app/forms/Field.svelte | 12 ++++++-- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/client/src/components/app/Button.svelte b/packages/client/src/components/app/Button.svelte index c43face1bb..29bdd46a70 100644 --- a/packages/client/src/components/app/Button.svelte +++ b/packages/client/src/components/app/Button.svelte @@ -5,8 +5,6 @@ const { styleable, builderStore } = getContext("sdk") const component = getContext("component") - let handlingOnClick = false - export let disabled = false export let text = "" export let onClick @@ -19,17 +17,9 @@ // For internal use only for now - not defined in the manifest export let active = false - const handleOnClick = async () => { - handlingOnClick = true - - if (onClick) { - await onClick() - } - - handlingOnClick = false - } - let node + let touched = false + let handlingOnClick = false $: $component.editing && node?.focus() $: componentText = getComponentText(text, $builderStore, $component) @@ -42,7 +32,18 @@ } const updateText = e => { - builderStore.actions.updateProp("text", e.target.textContent) + if (touched) { + builderStore.actions.updateProp("text", e.target.textContent) + } + touched = false + } + + const handleOnClick = async () => { + handlingOnClick = true + if (onClick) { + await onClick() + } + handlingOnClick = false } @@ -57,6 +58,7 @@ on:blur={$component.editing ? updateText : null} bind:this={node} class:active + on:input={() => (touched = true)} > {#if icon} diff --git a/packages/client/src/components/app/Heading.svelte b/packages/client/src/components/app/Heading.svelte index 4adec59e2b..103ac31a93 100644 --- a/packages/client/src/components/app/Heading.svelte +++ b/packages/client/src/components/app/Heading.svelte @@ -14,6 +14,7 @@ export let size let node + let touched = false $: $component.editing && node?.focus() $: placeholder = $builderStore.inBuilder && !text && !$component.editing @@ -47,7 +48,10 @@ // Convert contenteditable HTML to text and save const updateText = e => { - builderStore.actions.updateProp("text", e.target.textContent) + if (touched) { + builderStore.actions.updateProp("text", e.target.textContent) + } + touched = false } @@ -62,6 +66,7 @@ class:underline class="spectrum-Heading {sizeClass} {alignClass}" on:blur={$component.editing ? updateText : null} + on:input={() => (touched = true)} > {componentText} diff --git a/packages/client/src/components/app/Link.svelte b/packages/client/src/components/app/Link.svelte index 6cabcec7df..7eddcc6fe5 100644 --- a/packages/client/src/components/app/Link.svelte +++ b/packages/client/src/components/app/Link.svelte @@ -16,6 +16,7 @@ export let size let node + let touched = false $: $component.editing && node?.focus() $: externalLink = url && typeof url === "string" && !url.startsWith("/") @@ -62,7 +63,10 @@ } const updateText = e => { - builderStore.actions.updateProp("text", e.target.textContent) + if (touched) { + builderStore.actions.updateProp("text", e.target.textContent) + } + touched = false } @@ -76,6 +80,7 @@ class:underline class="align--{align || 'left'} size--{size || 'M'}" on:blur={$component.editing ? updateText : null} + on:input={() => (touched = true)} > {componentText} diff --git a/packages/client/src/components/app/Text.svelte b/packages/client/src/components/app/Text.svelte index 1037725ff8..fa15868d0f 100644 --- a/packages/client/src/components/app/Text.svelte +++ b/packages/client/src/components/app/Text.svelte @@ -13,6 +13,7 @@ export let size let node + let touched = false $: $component.editing && node?.focus() $: placeholder = $builderStore.inBuilder && !text && !$component.editing @@ -46,7 +47,10 @@ // Convert contenteditable HTML to text and save const updateText = e => { - builderStore.actions.updateProp("text", e.target.textContent) + if (touched) { + builderStore.actions.updateProp("text", e.target.textContent) + } + touched = false } @@ -61,6 +65,7 @@ class:underline class="spectrum-Body {sizeClass} {alignClass}" on:blur={$component.editing ? updateText : null} + on:input={() => (touched = true)} > {componentText}

diff --git a/packages/client/src/components/app/forms/Field.svelte b/packages/client/src/components/app/forms/Field.svelte index 74ff5442a9..9210b6ea8f 100644 --- a/packages/client/src/components/app/forms/Field.svelte +++ b/packages/client/src/components/app/forms/Field.svelte @@ -26,6 +26,10 @@ // Register field with form const formApi = formContext?.formApi const labelPos = fieldGroupContext?.labelPosition || "above" + + let touched = false + let labelNode + $: formStep = formStepContext ? $formStepContext || 1 : 1 $: formField = formApi?.registerField( field, @@ -36,14 +40,12 @@ validation, formStep ) - $: schemaType = fieldSchema?.type !== "formula" && fieldSchema?.type !== "bigint" ? fieldSchema?.type : "string" // Focus label when editing - let labelNode $: $component.editing && labelNode?.focus() // Update form properties in parent component on every store change @@ -57,7 +59,10 @@ $: labelClass = labelPos === "above" ? "" : `spectrum-FieldLabel--${labelPos}` const updateLabel = e => { - builderStore.actions.updateProp("label", e.target.textContent) + if (touched) { + builderStore.actions.updateProp("label", e.target.textContent) + } + touched = false } onDestroy(() => { @@ -79,6 +84,7 @@ bind:this={labelNode} contenteditable={$component.editing} on:blur={$component.editing ? updateLabel : null} + on:input={() => (touched = true)} class:hidden={!label} class:readonly for={fieldState?.fieldId} From ae863a6e16efa2b7c8114155a7dd4eb04aede625 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 10 Jun 2024 08:00:58 +0100 Subject: [PATCH 2/9] Only override grid column widths in table block when they are defined --- packages/client/src/components/app/GridBlock.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index dbd651b533..7502dc1ba8 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -90,9 +90,11 @@ columns.forEach((column, idx) => { overrides[column.field] = { displayName: column.label, - width: column.width, order: idx, } + if (column.width) { + overrides[column.field].width = column.width + } }) return overrides } From 08a48a9ff91ccf10524e768874f953c35f2771c0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 10 Jun 2024 08:57:24 +0100 Subject: [PATCH 3/9] Make new schema validation errors visible to users, and reset schema when saving fails --- .../src/components/grid/stores/datasource.js | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/frontend-core/src/components/grid/stores/datasource.js b/packages/frontend-core/src/components/grid/stores/datasource.js index 09b8be4868..8b8ffdf2cf 100644 --- a/packages/frontend-core/src/components/grid/stores/datasource.js +++ b/packages/frontend-core/src/components/grid/stores/datasource.js @@ -94,6 +94,7 @@ export const createActions = context => { nonPlus, schemaMutations, schema, + notifications, } = context // Gets the appropriate API for the configured datasource type @@ -125,16 +126,25 @@ export const createActions = context => { // Saves the datasource definition const saveDefinition = async newDefinition => { // Update local state + const originalDefinition = get(definition) definition.set(newDefinition) // Update server if (get(config).canSaveSchema) { - await getAPI()?.actions.saveDefinition(newDefinition) + try { + await getAPI()?.actions.saveDefinition(newDefinition) - // Broadcast change so external state can be updated, as this change - // will not be received by the builder websocket because we caused it - // ourselves - dispatch("updatedatasource", newDefinition) + // Broadcast change so external state can be updated, as this change + // will not be received by the builder websocket because we caused it + // ourselves + dispatch("updatedatasource", newDefinition) + } catch (error) { + const msg = error?.message || error || "Unknown error" + get(notifications).error(`Error saving schema: ${msg}`) + + // Reset the definition if saving failed + definition.set(originalDefinition) + } } } From 7566ecfac8166677018a29b95020d1a569fffdd0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 10 Jun 2024 09:40:08 +0100 Subject: [PATCH 4/9] Fix issue where grid highlighted rows are incorrect when page is scrolled --- .../components/grid/layout/GridBody.svelte | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/frontend-core/src/components/grid/layout/GridBody.svelte b/packages/frontend-core/src/components/grid/layout/GridBody.svelte index 87fcfe2d32..8be56674be 100644 --- a/packages/frontend-core/src/components/grid/layout/GridBody.svelte +++ b/packages/frontend-core/src/components/grid/layout/GridBody.svelte @@ -23,14 +23,24 @@ 0 ) + const updateBounds = () => { + bounds.set(body.getBoundingClientRect()) + } + onMount(() => { // Observe and record the height of the body - const observer = new ResizeObserver(() => { - bounds.set(body.getBoundingClientRect()) - }) - observer.observe(body) + const resizeObserver = new ResizeObserver(updateBounds) + resizeObserver.observe(body) + + // Capture any wheel events on the page to ensure our scroll offset is + // correct. We don't care about touch events as we only need this for + // hovering over rows with a mouse. + window.addEventListener("wheel", updateBounds, true) + + // Clean up listeners return () => { - observer.disconnect() + resizeObserver.disconnect() + window.removeEventListener("wheel", updateBounds, true) } }) From 9047c54b03084dd97accd1132f83b71a04ca0e3b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 10 Jun 2024 09:52:49 +0100 Subject: [PATCH 5/9] Truncate long column names in column settings buttons --- .../grid/controls/ColumnsSettingButton.svelte | 14 ++++++++++++-- .../grid/controls/ToggleActionButtonGroup.svelte | 1 - 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte b/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte index ed94a01e56..f16a1183a4 100644 --- a/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte +++ b/packages/frontend-core/src/components/grid/controls/ColumnsSettingButton.svelte @@ -116,7 +116,9 @@ {#each displayColumns as column}
- {column.label} +
+ {column.label} +
toggleColumn(column, e.detail)} @@ -139,7 +141,8 @@ display: grid; align-items: center; grid-template-columns: 1fr auto; - gap: 8px; + grid-row-gap: 8px; + grid-column-gap: 24px; } .columns :global(.spectrum-Switch) { margin-right: 0; @@ -148,4 +151,11 @@ display: flex; gap: 8px; } + .column-label { + min-width: 80px; + max-width: 200px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } diff --git a/packages/frontend-core/src/components/grid/controls/ToggleActionButtonGroup.svelte b/packages/frontend-core/src/components/grid/controls/ToggleActionButtonGroup.svelte index 2e62c593d1..497e77c2c9 100644 --- a/packages/frontend-core/src/components/grid/controls/ToggleActionButtonGroup.svelte +++ b/packages/frontend-core/src/components/grid/controls/ToggleActionButtonGroup.svelte @@ -29,7 +29,6 @@ .permissionPicker { display: flex; gap: var(--spacing-xs); - padding-left: calc(var(--spacing-xl) * 2); } .permissionPicker :global(.spectrum-Icon) { From 6a859e568b17d83d8f98ca75ea1dca117b6f1439 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 10 Jun 2024 13:28:04 +0100 Subject: [PATCH 6/9] Fix missing on:change event proxy from builder dropzone component --- packages/builder/src/components/common/Dropzone.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/builder/src/components/common/Dropzone.svelte b/packages/builder/src/components/common/Dropzone.svelte index 37569df0d5..8cd85e2530 100644 --- a/packages/builder/src/components/common/Dropzone.svelte +++ b/packages/builder/src/components/common/Dropzone.svelte @@ -38,4 +38,5 @@ {processFiles} handleFileTooLarge={$admin.cloud ? handleFileTooLarge : null} {fileSizeLimit} + on:change /> From 4cfa02f5d2f44d8dcdd6b65bce84ec3f44b7b7f3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 10 Jun 2024 13:59:35 +0100 Subject: [PATCH 7/9] Fix options not clearing when adding select-type columns --- .../components/backend/DataTable/modals/CreateEditColumn.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index 730e51bf48..17ecd8f844 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -334,7 +334,7 @@ // Add in defaults and initial definition const definition = fieldDefinitions[type?.toUpperCase()] if (definition?.constraints) { - editableColumn.constraints = definition.constraints + editableColumn.constraints = cloneDeep(definition.constraints) } editableColumn.type = definition.type From 387b9a8ed2854931268b1b5883459aaa37a04641 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 11 Jun 2024 16:19:57 +0100 Subject: [PATCH 8/9] Ensure input fields don't exceed cell bounds in grids in firefox --- packages/frontend-core/src/components/grid/cells/TextCell.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/frontend-core/src/components/grid/cells/TextCell.svelte b/packages/frontend-core/src/components/grid/cells/TextCell.svelte index d2ee0189fe..0cf0ab2004 100644 --- a/packages/frontend-core/src/components/grid/cells/TextCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/TextCell.svelte @@ -81,6 +81,7 @@ } input { flex: 1 1 auto; + width: 0; border: none; padding: var(--cell-padding); overflow: hidden; From 783d21159abb2b930531fa24eba854185a6fcaf2 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 11 Jun 2024 16:53:17 +0100 Subject: [PATCH 9/9] Lint --- .../controls/DataSourceSelect/DataSourceSelect.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte b/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte index a3ea677df9..d2b5174139 100644 --- a/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/DataSourceSelect/DataSourceSelect.svelte @@ -55,7 +55,9 @@ label: m.name, tableId: m._id, type: "table", - datasource: $datasources.list.find(ds => ds._id === m.sourceId || m.datasourceId), + datasource: $datasources.list.find( + ds => ds._id === m.sourceId || m.datasourceId + ), })) $: viewsV1 = $viewsStore.list.map(view => ({ ...view,