Merge branch 'develop' of github.com:Budibase/budibase into merge/master-develop-29-06-23
This commit is contained in:
commit
488e7b9502
|
@ -71,6 +71,7 @@
|
||||||
timeOnly,
|
timeOnly,
|
||||||
enableTime,
|
enableTime,
|
||||||
time24hr,
|
time24hr,
|
||||||
|
disabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChange = event => {
|
const handleChange = event => {
|
||||||
|
|
|
@ -155,6 +155,7 @@ export const getFrontendStore = () => {
|
||||||
...INITIAL_FRONTEND_STATE.features,
|
...INITIAL_FRONTEND_STATE.features,
|
||||||
...application.features,
|
...application.features,
|
||||||
},
|
},
|
||||||
|
icon: application.icon || {},
|
||||||
initialised: true,
|
initialised: true,
|
||||||
}))
|
}))
|
||||||
screenHistoryStore.reset()
|
screenHistoryStore.reset()
|
||||||
|
@ -235,6 +236,7 @@ export const getFrontendStore = () => {
|
||||||
legalDirectChildren = []
|
legalDirectChildren = []
|
||||||
) => {
|
) => {
|
||||||
const type = component._component
|
const type = component._component
|
||||||
|
|
||||||
if (illegalChildren.includes(type)) {
|
if (illegalChildren.includes(type)) {
|
||||||
return type
|
return type
|
||||||
}
|
}
|
||||||
|
@ -248,10 +250,13 @@ export const getFrontendStore = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === "@budibase/standard-components/sidepanel") {
|
||||||
|
illegalChildren = []
|
||||||
|
}
|
||||||
|
|
||||||
const definition = store.actions.components.getDefinition(
|
const definition = store.actions.components.getDefinition(
|
||||||
component._component
|
component._component
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reset whitelist for direct children
|
// Reset whitelist for direct children
|
||||||
legalDirectChildren = []
|
legalDirectChildren = []
|
||||||
if (definition?.legalDirectChildren?.length) {
|
if (definition?.legalDirectChildren?.length) {
|
||||||
|
|
|
@ -275,7 +275,7 @@
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedApp ? `${selectedApp?.url}` : ""}
|
{$store.url}
|
||||||
{#if isPublished}
|
{#if isPublished}
|
||||||
<Icon size="S" name="LinkOut" />
|
<Icon size="S" name="LinkOut" />
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -344,7 +344,12 @@
|
||||||
|
|
||||||
<Modal bind:this={updateAppModal} padding={false} width="600px">
|
<Modal bind:this={updateAppModal} padding={false} width="600px">
|
||||||
<UpdateAppModal
|
<UpdateAppModal
|
||||||
app={selectedApp}
|
app={{
|
||||||
|
name: $store.name,
|
||||||
|
url: $store.url,
|
||||||
|
icon: $store.icon,
|
||||||
|
appId: $store.appId,
|
||||||
|
}}
|
||||||
onUpdateComplete={async () => {
|
onUpdateComplete={async () => {
|
||||||
await initialiseApp()
|
await initialiseApp()
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
export let app
|
export let app
|
||||||
export let onUpdateComplete
|
export let onUpdateComplete
|
||||||
|
|
||||||
|
$: appIdParts = app.appId ? app.appId?.split("_") : []
|
||||||
|
$: appId = appIdParts.slice(-1)[0]
|
||||||
|
|
||||||
const values = writable({
|
const values = writable({
|
||||||
name: app.name,
|
name: app.name,
|
||||||
url: app.url,
|
url: app.url,
|
||||||
|
@ -35,8 +38,20 @@
|
||||||
|
|
||||||
const setupValidation = async () => {
|
const setupValidation = async () => {
|
||||||
const applications = svelteGet(apps)
|
const applications = svelteGet(apps)
|
||||||
appValidation.name(validation, { apps: applications, currentApp: app })
|
appValidation.name(validation, {
|
||||||
appValidation.url(validation, { apps: applications, currentApp: app })
|
apps: applications,
|
||||||
|
currentApp: {
|
||||||
|
...app,
|
||||||
|
appId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
appValidation.url(validation, {
|
||||||
|
apps: applications,
|
||||||
|
currentApp: {
|
||||||
|
...app,
|
||||||
|
appId,
|
||||||
|
},
|
||||||
|
})
|
||||||
// init validation
|
// init validation
|
||||||
const { url } = $values
|
const { url } = $values
|
||||||
validation.check({
|
validation.check({
|
||||||
|
@ -47,7 +62,7 @@
|
||||||
|
|
||||||
async function updateApp() {
|
async function updateApp() {
|
||||||
try {
|
try {
|
||||||
await apps.update(app.instance._id, {
|
await apps.update(app.appId, {
|
||||||
name: $values.name?.trim(),
|
name: $values.name?.trim(),
|
||||||
url: $values.url?.trim(),
|
url: $values.url?.trim(),
|
||||||
icon: {
|
icon: {
|
||||||
|
|
|
@ -52,7 +52,13 @@ export const url = (validation, { apps, currentApp } = { apps: [] }) => {
|
||||||
}
|
}
|
||||||
return !apps
|
return !apps
|
||||||
.map(app => app.url)
|
.map(app => app.url)
|
||||||
.some(appUrl => appUrl?.toLowerCase() === value.toLowerCase())
|
.some(appUrl => {
|
||||||
|
const url =
|
||||||
|
appUrl?.[0] === "/"
|
||||||
|
? appUrl.substring(1, appUrl.length)
|
||||||
|
: appUrl
|
||||||
|
return url?.toLowerCase() === value.toLowerCase()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.test("valid-url", "Not a valid URL", value => {
|
.test("valid-url", "Not a valid URL", value => {
|
||||||
|
|
|
@ -52,6 +52,9 @@
|
||||||
// Build up list of illegal children from ancestors
|
// Build up list of illegal children from ancestors
|
||||||
let illegalChildren = definition.illegalChildren || []
|
let illegalChildren = definition.illegalChildren || []
|
||||||
path.forEach(ancestor => {
|
path.forEach(ancestor => {
|
||||||
|
if (ancestor._component === `@budibase/standard-components/sidepanel`) {
|
||||||
|
illegalChildren = []
|
||||||
|
}
|
||||||
const def = store.actions.components.getDefinition(ancestor._component)
|
const def = store.actions.components.getDefinition(ancestor._component)
|
||||||
const blacklist = def?.illegalChildren?.map(x => {
|
const blacklist = def?.illegalChildren?.map(x => {
|
||||||
return `@budibase/standard-components/${x}`
|
return `@budibase/standard-components/${x}`
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
notifications.success("Copied")
|
notifications.success("Copied")
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Copy Code
|
Copy code
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
@ -19,11 +19,10 @@
|
||||||
|
|
||||||
$: filteredApps = $apps.filter(app => app.devId == $store.appId)
|
$: filteredApps = $apps.filter(app => app.devId == $store.appId)
|
||||||
$: app = filteredApps.length ? filteredApps[0] : {}
|
$: app = filteredApps.length ? filteredApps[0] : {}
|
||||||
$: appUrl = `${window.origin}/app${app?.url}`
|
|
||||||
$: appDeployed = app?.status === AppStatus.DEPLOYED
|
$: appDeployed = app?.status === AppStatus.DEPLOYED
|
||||||
|
|
||||||
const initialiseApp = async () => {
|
const initialiseApp = async () => {
|
||||||
const applicationPkg = await API.fetchAppPackage(app.devId)
|
const applicationPkg = await API.fetchAppPackage($store.appId)
|
||||||
await store.actions.initialise(applicationPkg)
|
await store.actions.initialise(applicationPkg)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -37,7 +36,7 @@
|
||||||
|
|
||||||
<Layout noPadding gap="XXS">
|
<Layout noPadding gap="XXS">
|
||||||
<Label size="L">Name</Label>
|
<Label size="L">Name</Label>
|
||||||
<Body>{app?.name}</Body>
|
<Body>{$store?.name}</Body>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<Layout noPadding gap="XS">
|
<Layout noPadding gap="XS">
|
||||||
|
@ -45,15 +44,15 @@
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
size="L"
|
size="L"
|
||||||
name={app?.icon?.name || "Apps"}
|
name={$store?.icon?.name || "Apps"}
|
||||||
color={app?.icon?.color}
|
color={$store?.icon?.color}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<Layout noPadding gap="XXS">
|
<Layout noPadding gap="XXS">
|
||||||
<Label size="L">URL</Label>
|
<Label size="L">URL</Label>
|
||||||
<Body>{appUrl}</Body>
|
<Body>{$store.url}</Body>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -75,7 +74,12 @@
|
||||||
|
|
||||||
<Modal bind:this={updatingModal} padding={false} width="600px">
|
<Modal bind:this={updatingModal} padding={false} width="600px">
|
||||||
<UpdateAppModal
|
<UpdateAppModal
|
||||||
{app}
|
app={{
|
||||||
|
name: $store.name,
|
||||||
|
url: $store.url,
|
||||||
|
icon: $store.icon,
|
||||||
|
appId: $store.appId,
|
||||||
|
}}
|
||||||
onUpdateComplete={async () => {
|
onUpdateComplete={async () => {
|
||||||
await initialiseApp()
|
await initialiseApp()
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { writable, derived } from "svelte/store"
|
|
||||||
import { apps } from "./apps"
|
|
||||||
|
|
||||||
const createOverviewStore = () => {
|
|
||||||
const store = writable({
|
|
||||||
selectedAppId: null,
|
|
||||||
})
|
|
||||||
const derivedStore = derived([store, apps], ([$store, $apps]) => {
|
|
||||||
return {
|
|
||||||
...$store,
|
|
||||||
selectedApp: $apps?.find(app => app.devId === $store.selectedAppId),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
update: store.update,
|
|
||||||
subscribe: derivedStore.subscribe,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const overview = createOverviewStore()
|
|
|
@ -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