Merge branch 'develop' of github.com:Budibase/budibase into merge/master-develop-29-06-23

This commit is contained in:
mike12345567 2023-06-30 11:37:03 +01:00
commit 488e7b9502
20 changed files with 142 additions and 57 deletions

View File

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

View File

@ -155,6 +155,7 @@ export const getFrontendStore = () => {
...INITIAL_FRONTEND_STATE.features,
...application.features,
},
icon: application.icon || {},
initialised: true,
}))
screenHistoryStore.reset()
@ -235,6 +236,7 @@ export const getFrontendStore = () => {
legalDirectChildren = []
) => {
const type = component._component
if (illegalChildren.includes(type)) {
return type
}
@ -248,10 +250,13 @@ export const getFrontendStore = () => {
return
}
if (type === "@budibase/standard-components/sidepanel") {
illegalChildren = []
}
const definition = store.actions.components.getDefinition(
component._component
)
// Reset whitelist for direct children
legalDirectChildren = []
if (definition?.legalDirectChildren?.length) {

View File

@ -275,7 +275,7 @@
}
}}
>
{selectedApp ? `${selectedApp?.url}` : ""}
{$store.url}
{#if isPublished}
<Icon size="S" name="LinkOut" />
{:else}
@ -344,7 +344,12 @@
<Modal bind:this={updateAppModal} padding={false} width="600px">
<UpdateAppModal
app={selectedApp}
app={{
name: $store.name,
url: $store.url,
icon: $store.icon,
appId: $store.appId,
}}
onUpdateComplete={async () => {
await initialiseApp()
}}

View File

@ -16,6 +16,9 @@
export let app
export let onUpdateComplete
$: appIdParts = app.appId ? app.appId?.split("_") : []
$: appId = appIdParts.slice(-1)[0]
const values = writable({
name: app.name,
url: app.url,
@ -35,8 +38,20 @@
const setupValidation = async () => {
const applications = svelteGet(apps)
appValidation.name(validation, { apps: applications, currentApp: app })
appValidation.url(validation, { apps: applications, currentApp: app })
appValidation.name(validation, {
apps: applications,
currentApp: {
...app,
appId,
},
})
appValidation.url(validation, {
apps: applications,
currentApp: {
...app,
appId,
},
})
// init validation
const { url } = $values
validation.check({
@ -47,7 +62,7 @@
async function updateApp() {
try {
await apps.update(app.instance._id, {
await apps.update(app.appId, {
name: $values.name?.trim(),
url: $values.url?.trim(),
icon: {

View File

@ -52,7 +52,13 @@ export const url = (validation, { apps, currentApp } = { apps: [] }) => {
}
return !apps
.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 => {

View File

@ -52,6 +52,9 @@
// Build up list of illegal children from ancestors
let illegalChildren = definition.illegalChildren || []
path.forEach(ancestor => {
if (ancestor._component === `@budibase/standard-components/sidepanel`) {
illegalChildren = []
}
const def = store.actions.components.getDefinition(ancestor._component)
const blacklist = def?.illegalChildren?.map(x => {
return `@budibase/standard-components/${x}`

View File

@ -39,7 +39,7 @@
notifications.success("Copied")
}}
>
Copy Code
Copy code
</Button>
</div>
{:else}

View File

@ -19,11 +19,10 @@
$: filteredApps = $apps.filter(app => app.devId == $store.appId)
$: app = filteredApps.length ? filteredApps[0] : {}
$: appUrl = `${window.origin}/app${app?.url}`
$: appDeployed = app?.status === AppStatus.DEPLOYED
const initialiseApp = async () => {
const applicationPkg = await API.fetchAppPackage(app.devId)
const applicationPkg = await API.fetchAppPackage($store.appId)
await store.actions.initialise(applicationPkg)
}
</script>
@ -37,7 +36,7 @@
<Layout noPadding gap="XXS">
<Label size="L">Name</Label>
<Body>{app?.name}</Body>
<Body>{$store?.name}</Body>
</Layout>
<Layout noPadding gap="XS">
@ -45,15 +44,15 @@
<div class="icon">
<Icon
size="L"
name={app?.icon?.name || "Apps"}
color={app?.icon?.color}
name={$store?.icon?.name || "Apps"}
color={$store?.icon?.color}
/>
</div>
</Layout>
<Layout noPadding gap="XXS">
<Label size="L">URL</Label>
<Body>{appUrl}</Body>
<Body>{$store.url}</Body>
</Layout>
<div>
@ -75,7 +74,12 @@
<Modal bind:this={updatingModal} padding={false} width="600px">
<UpdateAppModal
{app}
app={{
name: $store.name,
url: $store.url,
icon: $store.icon,
appId: $store.appId,
}}
onUpdateComplete={async () => {
await initialiseApp()
}}

View File

@ -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()

View File

@ -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}
/>
</div>

View File

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

View File

@ -1,8 +1,8 @@
<script>
import { Modal, ModalContent, notifications } from "@budibase/bbui"
import { Modal, ModalContent } from "@budibase/bbui"
import { getContext, onMount } from "svelte"
const { selectedRows, rows, subscribe } = getContext("grid")
const { selectedRows, rows, subscribe, notifications } = getContext("grid")
let modal
@ -15,7 +15,7 @@
const performDeletion = async () => {
const count = rowsToDelete.length
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()))

View File

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

View File

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

View File

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

View File

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

View File

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

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 { fetchData } from "../../../fetch/fetchData"
import { notifications } from "@budibase/bbui"
import { NewRowID, RowPageSize } from "../lib/constants"
import { tick } from "svelte"
@ -71,6 +70,7 @@ export const deriveStores = context => {
previousFocusedRowId,
hasNextPage,
error,
notifications,
} = context
const instanceLoaded = writable(false)
const fetch = writable(null)
@ -203,10 +203,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 +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
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 +271,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) {