From c7122448e176515506391f0d6cbbcf070229bd20 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 28 Jun 2023 09:18:01 +0100 Subject: [PATCH 1/4] Fix notifications not working in grid blocks in client apps --- .../src/components/app/GridBlock.svelte | 4 ++- .../grid/cells/AttachmentCell.svelte | 8 ++--- .../grid/controls/BulkDeleteHandler.svelte | 6 ++-- .../src/components/grid/layout/Grid.svelte | 4 +++ .../grid/overlays/MenuOverlay.svelte | 13 +++----- .../src/components/grid/stores/columns.js | 11 +++++++ .../src/components/grid/stores/config.js | 4 +++ .../src/components/grid/stores/index.js | 2 ++ .../components/grid/stores/notifications.js | 23 ++++++++++++++ .../src/components/grid/stores/rows.js | 30 ++++++++++++++++--- 10 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 packages/frontend-core/src/components/grid/stores/notifications.js diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index 4314f6e99c..3f2509f19b 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -16,7 +16,7 @@ export let columns = null const component = getContext("component") - const { styleable, API, builderStore } = getContext("sdk") + const { styleable, API, builderStore, notificationStore } = getContext("sdk") $: columnWhitelist = columns?.map(col => col.name) $: schemaOverrides = getSchemaOverrides(columns) @@ -52,6 +52,8 @@ showControls={false} allowExpandRows={false} allowSchemaChanges={false} + notifySuccess={notificationStore.actions.success} + notifyError={notificationStore.actions.error} /> diff --git a/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte b/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte index c80b12cf1a..a27c31bbe5 100644 --- a/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/AttachmentCell.svelte @@ -1,7 +1,7 @@ diff --git a/packages/frontend-core/src/components/grid/stores/columns.js b/packages/frontend-core/src/components/grid/stores/columns.js index 664e67950e..21458eaefb 100644 --- a/packages/frontend-core/src/components/grid/stores/columns.js +++ b/packages/frontend-core/src/components/grid/stores/columns.js @@ -35,10 +35,20 @@ export const createStores = () => { [] ) + // Checks if we have a certain column by name + const hasColumn = column => { + const $columns = get(columns) + const $sticky = get(stickyColumn) + return $columns.some(col => col.name === column) || $sticky?.name === column + } + return { columns: { ...columns, subscribe: enrichedColumns.subscribe, + actions: { + hasColumn, + }, }, stickyColumn, visibleColumns, @@ -121,6 +131,7 @@ export const deriveStores = context => { columns: { ...columns, actions: { + ...columns.actions, saveChanges, saveTable, changePrimaryDisplay, diff --git a/packages/frontend-core/src/components/grid/stores/config.js b/packages/frontend-core/src/components/grid/stores/config.js index 2fe9bafa91..cdf71e161b 100644 --- a/packages/frontend-core/src/components/grid/stores/config.js +++ b/packages/frontend-core/src/components/grid/stores/config.js @@ -13,6 +13,8 @@ export const createStores = context => { const initialRowHeight = getProp("initialRowHeight") const schemaOverrides = getProp("schemaOverrides") const columnWhitelist = getProp("columnWhitelist") + const notifySuccess = getProp("notifySuccess") + const notifyError = getProp("notifyError") return { config, @@ -23,5 +25,7 @@ export const createStores = context => { initialRowHeight, schemaOverrides, columnWhitelist, + notifySuccess, + notifyError, } } diff --git a/packages/frontend-core/src/components/grid/stores/index.js b/packages/frontend-core/src/components/grid/stores/index.js index 588b568c8e..2a52b55f59 100644 --- a/packages/frontend-core/src/components/grid/stores/index.js +++ b/packages/frontend-core/src/components/grid/stores/index.js @@ -14,9 +14,11 @@ import * as Clipboard from "./clipboard" import * as Config from "./config" import * as Sort from "./sort" import * as Filter from "./filter" +import * as Notifications from "./notifications" const DependencyOrderedStores = [ Config, + Notifications, Sort, Filter, Bounds, diff --git a/packages/frontend-core/src/components/grid/stores/notifications.js b/packages/frontend-core/src/components/grid/stores/notifications.js new file mode 100644 index 0000000000..4e8b49414d --- /dev/null +++ b/packages/frontend-core/src/components/grid/stores/notifications.js @@ -0,0 +1,23 @@ +import { notifications as BBUINotifications } from "@budibase/bbui" +import { derived } from "svelte/store" + +export const createStores = context => { + const { notifySuccess, notifyError } = context + + // Normally we would not derive a store in "createStores" as it should be + // dependency free, but in this case it's safe as we only depend on grid props + // which are guaranteed to be first in the dependency chain + const notifications = derived( + [notifySuccess, notifyError], + ([$notifySuccess, $notifyError]) => { + return { + success: $notifySuccess || BBUINotifications.success, + error: $notifyError || BBUINotifications.error, + } + } + ) + + return { + notifications, + } +} diff --git a/packages/frontend-core/src/components/grid/stores/rows.js b/packages/frontend-core/src/components/grid/stores/rows.js index d348d5caa5..591dddf865 100644 --- a/packages/frontend-core/src/components/grid/stores/rows.js +++ b/packages/frontend-core/src/components/grid/stores/rows.js @@ -1,6 +1,5 @@ import { writable, derived, get } from "svelte/store" import { fetchData } from "../../../fetch/fetchData" -import { notifications } from "@budibase/bbui" import { NewRowID, RowPageSize } from "../lib/constants" import { tick } from "svelte" @@ -66,11 +65,13 @@ export const deriveStores = context => { validation, focusedCellId, columns, + stickyColumn, rowChangeCache, inProgressChanges, previousFocusedRowId, hasNextPage, error, + notifications, } = context const instanceLoaded = writable(false) const fetch = writable(null) @@ -203,10 +204,23 @@ export const deriveStores = context => { // state, storing error messages against relevant cells const handleValidationError = (rowId, error) => { if (error?.json?.validationErrors) { - // Normal validation error + // Normal validation errors const keys = Object.keys(error.json.validationErrors) const $columns = get(columns) + + // Filter out missing columns from columns that we have + let erroredColumns = [] + let missingColumns = [] for (let column of keys) { + if (columns.actions.hasColumn(column)) { + erroredColumns.push(column) + } else { + missingColumns.push(column) + } + } + + // Process errors for columns that we have + for (let column of erroredColumns) { validation.actions.setError( `${rowId}-${column}`, `${column} ${error.json.validationErrors[column]}` @@ -221,8 +235,16 @@ export const deriveStores = context => { }) } } + + // Notify about missing columns + for (let column of missingColumns) { + get(notifications).error(`${column} is required but is missing`) + } + // Focus the first cell with an error - focusedCellId.set(`${rowId}-${keys[0]}`) + if (erroredColumns.length) { + focusedCellId.set(`${rowId}-${erroredColumns[0]}`) + } } else { // Some other error - just update the current cell validation.actions.setError(get(focusedCellId), error?.message || "Error") @@ -250,7 +272,7 @@ export const deriveStores = context => { } // Refresh row to ensure data is in the correct format - notifications.success("Row created successfully") + get(notifications).success("Row created successfully") return newRow } catch (error) { if (bubble) { From ce004d39d19ed5daf5307e97abe818609c87f736 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 28 Jun 2023 09:26:45 +0100 Subject: [PATCH 2/4] Fix grid keybind for submitting new rows not working --- .../frontend-core/src/components/grid/layout/NewRow.svelte | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/frontend-core/src/components/grid/layout/NewRow.svelte b/packages/frontend-core/src/components/grid/layout/NewRow.svelte index b6b5925027..f1870c2638 100644 --- a/packages/frontend-core/src/components/grid/layout/NewRow.svelte +++ b/packages/frontend-core/src/components/grid/layout/NewRow.svelte @@ -78,6 +78,11 @@ } const startAdding = async () => { + // Attempt to submit if already adding a row + if (visible && !isAdding) { + await addRow() + return + } if (visible || !firstColumn) { return } From 9e089192ef667451a12056468fc261b81727b170 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 28 Jun 2023 09:40:06 +0100 Subject: [PATCH 3/4] Lint --- packages/frontend-core/src/components/grid/stores/rows.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend-core/src/components/grid/stores/rows.js b/packages/frontend-core/src/components/grid/stores/rows.js index 591dddf865..736863378f 100644 --- a/packages/frontend-core/src/components/grid/stores/rows.js +++ b/packages/frontend-core/src/components/grid/stores/rows.js @@ -65,7 +65,6 @@ export const deriveStores = context => { validation, focusedCellId, columns, - stickyColumn, rowChangeCache, inProgressChanges, previousFocusedRowId, From 16bd879f5de65701d17f3e804eacf1aa85c4339a Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 28 Jun 2023 11:35:36 +0100 Subject: [PATCH 4/4] Fix issue with datepickers not working after starting off as disabled --- packages/bbui/src/Form/Core/DatePicker.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/bbui/src/Form/Core/DatePicker.svelte b/packages/bbui/src/Form/Core/DatePicker.svelte index ad39136142..7ce15292be 100644 --- a/packages/bbui/src/Form/Core/DatePicker.svelte +++ b/packages/bbui/src/Form/Core/DatePicker.svelte @@ -71,6 +71,7 @@ timeOnly, enableTime, time24hr, + disabled, } const handleChange = event => {