Merge pull request #11049 from Budibase/grid-block-notifications
Grid fixes
This commit is contained in:
commit
a1a8e74f43
|
@ -71,6 +71,7 @@
|
||||||
timeOnly,
|
timeOnly,
|
||||||
enableTime,
|
enableTime,
|
||||||
time24hr,
|
time24hr,
|
||||||
|
disabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChange = event => {
|
const handleChange = event => {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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 []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue