Merge pull request #11049 from Budibase/grid-block-notifications

Grid fixes
This commit is contained in:
Andrew Kingston 2023-06-30 11:30:34 +01:00 committed by GitHub
commit a1a8e74f43
12 changed files with 89 additions and 21 deletions

View File

@ -71,6 +71,7 @@
timeOnly, timeOnly,
enableTime, enableTime,
time24hr, time24hr,
disabled,
} }
const handleChange = event => { const handleChange = event => {

View File

@ -16,7 +16,7 @@
export let columns = null export let columns = null
const component = getContext("component") const component = getContext("component")
const { styleable, API, builderStore } = getContext("sdk") const { styleable, API, builderStore, notificationStore } = getContext("sdk")
$: columnWhitelist = columns?.map(col => col.name) $: columnWhitelist = columns?.map(col => col.name)
$: schemaOverrides = getSchemaOverrides(columns) $: schemaOverrides = getSchemaOverrides(columns)
@ -52,6 +52,8 @@
showControls={false} showControls={false}
allowExpandRows={false} allowExpandRows={false}
allowSchemaChanges={false} allowSchemaChanges={false}
notifySuccess={notificationStore.actions.success}
notifyError={notificationStore.actions.error}
/> />
</div> </div>

View File

@ -1,7 +1,7 @@
<script> <script>
import { onMount } from "svelte" import { onMount } from "svelte"
import { getContext } from "svelte" import { getContext } from "svelte"
import { Dropzone, notifications } from "@budibase/bbui" import { Dropzone } from "@budibase/bbui"
export let value export let value
export let focused = false export let focused = false
@ -11,7 +11,7 @@
export let invertX = false export let invertX = false
export let invertY = false export let invertY = false
const { API } = getContext("grid") const { API, notifications } = getContext("grid")
const imageExtensions = ["png", "tiff", "gif", "raw", "jpg", "jpeg"] const imageExtensions = ["png", "tiff", "gif", "raw", "jpg", "jpeg"]
let isOpen = false let isOpen = false
@ -40,7 +40,7 @@
} }
const handleFileTooLarge = fileSizeLimit => { const handleFileTooLarge = fileSizeLimit => {
notifications.error( $notifications.error(
`Files cannot exceed ${ `Files cannot exceed ${
fileSizeLimit / 1000000 fileSizeLimit / 1000000
}MB. Please try again with smaller files.` }MB. Please try again with smaller files.`
@ -55,7 +55,7 @@
try { try {
return await API.uploadBuilderAttachment(data) return await API.uploadBuilderAttachment(data)
} catch (error) { } catch (error) {
notifications.error("Failed to upload attachment") $notifications.error("Failed to upload attachment")
return [] return []
} }
} }

View File

@ -1,8 +1,8 @@
<script> <script>
import { Modal, ModalContent, notifications } from "@budibase/bbui" import { Modal, ModalContent } from "@budibase/bbui"
import { getContext, onMount } from "svelte" import { getContext, onMount } from "svelte"
const { selectedRows, rows, subscribe } = getContext("grid") const { selectedRows, rows, subscribe, notifications } = getContext("grid")
let modal let modal
@ -15,7 +15,7 @@
const performDeletion = async () => { const performDeletion = async () => {
const count = rowsToDelete.length const count = rowsToDelete.length
await rows.actions.deleteRows(rowsToDelete) await rows.actions.deleteRows(rowsToDelete)
notifications.success(`Deleted ${count} row${count === 1 ? "" : "s"}`) $notifications.success(`Deleted ${count} row${count === 1 ? "" : "s"}`)
} }
onMount(() => subscribe("request-bulk-delete", () => modal?.show())) onMount(() => subscribe("request-bulk-delete", () => modal?.show()))

View File

@ -44,6 +44,8 @@
export let initialSortColumn = null export let initialSortColumn = null
export let initialSortOrder = null export let initialSortOrder = null
export let initialRowHeight = null export let initialRowHeight = null
export let notifySuccess = null
export let notifyError = null
// Unique identifier for DOM nodes inside this instance // Unique identifier for DOM nodes inside this instance
const rand = Math.random() const rand = Math.random()
@ -89,6 +91,8 @@
initialSortColumn, initialSortColumn,
initialSortOrder, initialSortOrder,
initialRowHeight, initialRowHeight,
notifySuccess,
notifyError,
}) })
// Set context for children to consume // Set context for children to consume

View File

@ -78,6 +78,11 @@
} }
const startAdding = async () => { const startAdding = async () => {
// Attempt to submit if already adding a row
if (visible && !isAdding) {
await addRow()
return
}
if (visible || !firstColumn) { if (visible || !firstColumn) {
return return
} }

View File

@ -1,11 +1,5 @@
<script> <script>
import { import { clickOutside, Menu, MenuItem, Helpers } from "@budibase/bbui"
clickOutside,
Menu,
MenuItem,
Helpers,
notifications,
} from "@budibase/bbui"
import { getContext } from "svelte" import { getContext } from "svelte"
import { NewRowID } from "../lib/constants" import { NewRowID } from "../lib/constants"
@ -22,6 +16,7 @@
dispatch, dispatch,
focusedCellAPI, focusedCellAPI,
focusedRowId, focusedRowId,
notifications,
} = getContext("grid") } = getContext("grid")
$: style = makeStyle($menu) $: style = makeStyle($menu)
@ -34,7 +29,7 @@
const deleteRow = () => { const deleteRow = () => {
rows.actions.deleteRows([$focusedRow]) rows.actions.deleteRows([$focusedRow])
menu.actions.close() menu.actions.close()
notifications.success("Deleted 1 row") $notifications.success("Deleted 1 row")
} }
const duplicate = async () => { const duplicate = async () => {
@ -48,7 +43,7 @@
const copyToClipboard = async value => { const copyToClipboard = async value => {
await Helpers.copyToClipboard(value) await Helpers.copyToClipboard(value)
notifications.success("Copied to clipboard") $notifications.success("Copied to clipboard")
} }
</script> </script>

View File

@ -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 { return {
columns: { columns: {
...columns, ...columns,
subscribe: enrichedColumns.subscribe, subscribe: enrichedColumns.subscribe,
actions: {
hasColumn,
},
}, },
stickyColumn, stickyColumn,
visibleColumns, visibleColumns,
@ -121,6 +131,7 @@ export const deriveStores = context => {
columns: { columns: {
...columns, ...columns,
actions: { actions: {
...columns.actions,
saveChanges, saveChanges,
saveTable, saveTable,
changePrimaryDisplay, changePrimaryDisplay,

View File

@ -13,6 +13,8 @@ export const createStores = context => {
const initialRowHeight = getProp("initialRowHeight") const initialRowHeight = getProp("initialRowHeight")
const schemaOverrides = getProp("schemaOverrides") const schemaOverrides = getProp("schemaOverrides")
const columnWhitelist = getProp("columnWhitelist") const columnWhitelist = getProp("columnWhitelist")
const notifySuccess = getProp("notifySuccess")
const notifyError = getProp("notifyError")
return { return {
config, config,
@ -23,5 +25,7 @@ export const createStores = context => {
initialRowHeight, initialRowHeight,
schemaOverrides, schemaOverrides,
columnWhitelist, columnWhitelist,
notifySuccess,
notifyError,
} }
} }

View File

@ -14,9 +14,11 @@ import * as Clipboard from "./clipboard"
import * as Config from "./config" import * as Config from "./config"
import * as Sort from "./sort" import * as Sort from "./sort"
import * as Filter from "./filter" import * as Filter from "./filter"
import * as Notifications from "./notifications"
const DependencyOrderedStores = [ const DependencyOrderedStores = [
Config, Config,
Notifications,
Sort, Sort,
Filter, Filter,
Bounds, Bounds,

View File

@ -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,
}
}

View File

@ -1,6 +1,5 @@
import { writable, derived, get } from "svelte/store" import { writable, derived, get } from "svelte/store"
import { fetchData } from "../../../fetch/fetchData" import { fetchData } from "../../../fetch/fetchData"
import { notifications } from "@budibase/bbui"
import { NewRowID, RowPageSize } from "../lib/constants" import { NewRowID, RowPageSize } from "../lib/constants"
import { tick } from "svelte" import { tick } from "svelte"
@ -71,6 +70,7 @@ export const deriveStores = context => {
previousFocusedRowId, previousFocusedRowId,
hasNextPage, hasNextPage,
error, error,
notifications,
} = context } = context
const instanceLoaded = writable(false) const instanceLoaded = writable(false)
const fetch = writable(null) const fetch = writable(null)
@ -203,10 +203,23 @@ export const deriveStores = context => {
// state, storing error messages against relevant cells // state, storing error messages against relevant cells
const handleValidationError = (rowId, error) => { const handleValidationError = (rowId, error) => {
if (error?.json?.validationErrors) { if (error?.json?.validationErrors) {
// Normal validation error // Normal validation errors
const keys = Object.keys(error.json.validationErrors) const keys = Object.keys(error.json.validationErrors)
const $columns = get(columns) const $columns = get(columns)
// Filter out missing columns from columns that we have
let erroredColumns = []
let missingColumns = []
for (let column of keys) { 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( validation.actions.setError(
`${rowId}-${column}`, `${rowId}-${column}`,
`${column} ${error.json.validationErrors[column]}` `${column} ${error.json.validationErrors[column]}`
@ -221,8 +234,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 // Focus the first cell with an error
focusedCellId.set(`${rowId}-${keys[0]}`) if (erroredColumns.length) {
focusedCellId.set(`${rowId}-${erroredColumns[0]}`)
}
} else { } else {
// Some other error - just update the current cell // Some other error - just update the current cell
validation.actions.setError(get(focusedCellId), error?.message || "Error") validation.actions.setError(get(focusedCellId), error?.message || "Error")
@ -250,7 +271,7 @@ export const deriveStores = context => {
} }
// Refresh row to ensure data is in the correct format // Refresh row to ensure data is in the correct format
notifications.success("Row created successfully") get(notifications).success("Row created successfully")
return newRow return newRow
} catch (error) { } catch (error) {
if (bubble) { if (bubble) {