1
0
Fork 0
mirror of synced 2024-07-07 15:25:52 +12:00

Merge remote-tracking branch 'origin/develop' into feature/whitelabelling

This commit is contained in:
Dean 2023-03-27 15:21:35 +01:00
commit 1d97e2a908
30 changed files with 411 additions and 561 deletions

View file

@ -1,5 +1,5 @@
{
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"npmClient": "yarn",
"packages": [
"packages/*"

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/backend-core",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Budibase backend core libraries used in server and worker",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
@ -24,7 +24,7 @@
"dependencies": {
"@budibase/nano": "10.1.2",
"@budibase/pouchdb-replication-stream": "1.2.10",
"@budibase/types": "2.4.27-alpha.5",
"@budibase/types": "2.4.27-alpha.6",
"@shopify/jest-koa-mocks": "5.0.1",
"@techpass/passport-openidconnect": "0.3.2",
"aws-cloudfront-sign": "2.2.0",

View file

@ -1,7 +1,7 @@
{
"name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"license": "MPL-2.0",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",
@ -38,8 +38,8 @@
],
"dependencies": {
"@adobe/spectrum-css-workflow-icons": "1.2.1",
"@budibase/shared-core": "2.4.27-alpha.5",
"@budibase/string-templates": "2.4.27-alpha.5",
"@budibase/shared-core": "2.4.27-alpha.6",
"@budibase/string-templates": "2.4.27-alpha.6",
"@spectrum-css/accordion": "3.0.24",
"@spectrum-css/actionbutton": "1.0.1",
"@spectrum-css/actiongroup": "1.0.1",

View file

@ -1,56 +0,0 @@
<div class="skeleton">
<div class="children">
<slot />
</div>
</div>
<style>
.skeleton {
height: 100%;
width: 100%;
opacity: 0;
background-color: var(--spectrum-global-color-gray-200) !important;
border-radius: 7px;
overflow: hidden;
position: relative;
animation: fadeIn 130ms ease 0s 1 normal forwards;
}
.children {
pointer-events: none;
opacity: 0;
}
.skeleton::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.15) 20%,
rgba(255, 255, 255, 0.3) 60%,
rgba(255, 255, 255, 0)
);
animation: shimmer 2s infinite;
content: "";
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 0.75;
}
}
@keyframes shimmer {
100% {
transform: translateX(100%);
}
}
</style>

View file

@ -4,7 +4,6 @@ import "./bbui.css"
import "@spectrum-css/icon/dist/index-vars.css"
// Components
export { default as Skeleton } from "./Skeleton/Skeleton.svelte"
export { default as Input } from "./Form/Input.svelte"
export { default as Stepper } from "./Form/Stepper.svelte"
export { default as TextArea } from "./Form/TextArea.svelte"

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"license": "GPL-3.0",
"private": true,
"scripts": {
@ -58,11 +58,11 @@
}
},
"dependencies": {
"@budibase/bbui": "2.4.27-alpha.5",
"@budibase/client": "2.4.27-alpha.5",
"@budibase/frontend-core": "2.4.27-alpha.5",
"@budibase/shared-core": "2.4.27-alpha.5",
"@budibase/string-templates": "2.4.27-alpha.5",
"@budibase/bbui": "2.4.27-alpha.6",
"@budibase/client": "2.4.27-alpha.6",
"@budibase/frontend-core": "2.4.27-alpha.6",
"@budibase/shared-core": "2.4.27-alpha.6",
"@budibase/string-templates": "2.4.27-alpha.6",
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-brands-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/cli",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "dist/index.js",
"bin": {
@ -29,9 +29,9 @@
"outputPath": "build"
},
"dependencies": {
"@budibase/backend-core": "2.4.27-alpha.5",
"@budibase/string-templates": "2.4.27-alpha.5",
"@budibase/types": "2.4.27-alpha.5",
"@budibase/backend-core": "2.4.27-alpha.6",
"@budibase/string-templates": "2.4.27-alpha.6",
"@budibase/types": "2.4.27-alpha.6",
"axios": "0.21.2",
"chalk": "4.1.0",
"cli-progress": "3.11.2",

View file

@ -2346,7 +2346,6 @@
]
},
"stringfield": {
"skeleton": false,
"name": "Text Field",
"icon": "Text",
"styles": ["size"],
@ -2436,7 +2435,6 @@
]
},
"numberfield": {
"skeleton": false,
"name": "Number Field",
"icon": "123",
"styles": ["size"],
@ -2492,7 +2490,6 @@
]
},
"passwordfield": {
"skeleton": false,
"name": "Password Field",
"icon": "LockClosed",
"styles": ["size"],
@ -2548,7 +2545,6 @@
]
},
"optionsfield": {
"skeleton": false,
"name": "Options Picker",
"icon": "Menu",
"styles": ["size"],
@ -2715,7 +2711,6 @@
]
},
"multifieldselect": {
"skeleton": false,
"name": "Multi-select Picker",
"icon": "ViewList",
"styles": ["size"],
@ -2876,7 +2871,6 @@
]
},
"booleanfield": {
"skeleton": false,
"name": "Checkbox",
"icon": "SelectBox",
"editable": true,
@ -2955,7 +2949,6 @@
]
},
"longformfield": {
"skeleton": false,
"name": "Long Form Field",
"icon": "TextAlignLeft",
"styles": ["size"],
@ -3033,7 +3026,6 @@
]
},
"datetimefield": {
"skeleton": false,
"name": "Date Picker",
"icon": "Date",
"styles": ["size"],
@ -3113,7 +3105,6 @@
]
},
"codescanner": {
"skeleton": false,
"name": "Barcode/QR Scanner",
"icon": "Camera",
"styles": ["size"],
@ -3275,7 +3266,6 @@
]
},
"attachmentfield": {
"skeleton": false,
"name": "Attachment",
"icon": "Attach",
"styles": ["size"],
@ -3338,7 +3328,6 @@
]
},
"relationshipfield": {
"skeleton": false,
"name": "Relationship Picker",
"icon": "TaskList",
"styles": ["size"],
@ -3400,7 +3389,6 @@
]
},
"jsonfield": {
"skeleton": false,
"name": "JSON Field",
"icon": "Brackets",
"styles": ["size"],
@ -3591,7 +3579,6 @@
}
},
"table": {
"skeleton": false,
"name": "Table",
"icon": "Table",
"illegalChildren": ["section"],

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/client",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"license": "MPL-2.0",
"module": "dist/budibase-client.js",
"main": "dist/budibase-client.js",
@ -19,11 +19,11 @@
"dev:builder": "rollup -cw"
},
"dependencies": {
"@budibase/bbui": "2.4.27-alpha.5",
"@budibase/frontend-core": "2.4.27-alpha.5",
"@budibase/shared-core": "2.4.27-alpha.5",
"@budibase/string-templates": "2.4.27-alpha.5",
"@budibase/types": "2.4.27-alpha.5",
"@budibase/bbui": "2.4.27-alpha.6",
"@budibase/frontend-core": "2.4.27-alpha.6",
"@budibase/shared-core": "2.4.27-alpha.6",
"@budibase/string-templates": "2.4.27-alpha.6",
"@budibase/types": "2.4.27-alpha.6",
"@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3",

View file

@ -24,7 +24,6 @@
// to render this part of the block, taking advantage of binding enrichment
$: id = `${block.id}-${context ?? rand}`
$: instance = {
_blockElementHasChildren: $$slots?.default ?? false,
_component: `@budibase/standard-components/${type}`,
_id: id,
_instanceName: name || type[0].toUpperCase() + type.slice(1),

View file

@ -29,7 +29,6 @@
import Placeholder from "components/app/Placeholder.svelte"
import ScreenPlaceholder from "components/app/ScreenPlaceholder.svelte"
import ComponentPlaceholder from "components/app/ComponentPlaceholder.svelte"
import Skeleton from "components/app/Skeleton.svelte"
export let instance = {}
export let isLayout = false
@ -39,7 +38,6 @@
// Get parent contexts
const context = getContext("context")
const loading = getContext("loading")
const insideScreenslot = !!getContext("screenslot")
// Create component context
@ -172,15 +170,6 @@
$: pad = pad || (interactive && hasChildren && inDndPath)
$: $dndIsDragging, (pad = false)
// Determine whether we should render a skeleton loader for this component
$: showSkeleton =
$loading &&
definition?.name !== "Screenslot" &&
children.length === 0 &&
!instance._blockElementHasChildren &&
!definition?.block &&
definition?.skeleton !== false
// Update component context
$: store.set({
id,
@ -507,12 +496,7 @@
})
</script>
{#if showSkeleton}
<Skeleton
height={initialSettings?.height || definition?.size?.height || 0}
width={initialSettings?.width || definition?.size?.width || 0}
/>
{:else if constructor && initialSettings && (visible || inSelectedPath) && !builderHidden}
{#if constructor && initialSettings && (visible || inSelectedPath) && !builderHidden}
<!-- The ID is used as a class because getElementsByClassName is O(1) -->
<!-- and the performance matters for the selection indicators -->
<div
@ -530,23 +514,25 @@
data-icon={icon}
data-parent={parent}
>
<svelte:component this={constructor} bind:this={ref} {...initialSettings}>
{#if hasMissingRequiredSettings}
<ComponentPlaceholder />
{:else if children.length}
{#each children as child (child._id)}
<svelte:self instance={child} parent={id} />
{/each}
{:else if emptyState}
{#if isScreen}
<ScreenPlaceholder />
{:else}
<Placeholder />
{#if hasMissingRequiredSettings}
<ComponentPlaceholder />
{:else}
<svelte:component this={constructor} bind:this={ref} {...initialSettings}>
{#if children.length}
{#each children as child (child._id)}
<svelte:self instance={child} parent={id} />
{/each}
{:else if emptyState}
{#if isScreen}
<ScreenPlaceholder />
{:else}
<Placeholder />
{/if}
{:else if isBlock}
<slot />
{/if}
{:else if isBlock}
<slot />
{/if}
</svelte:component>
</svelte:component>
{/if}
</div>
{/if}

View file

@ -1,5 +1,4 @@
<script>
import { writable } from "svelte/store"
import { setContext, getContext, onMount } from "svelte"
import Router, { querystring } from "svelte-spa-router"
import { routeStore, stateStore } from "stores"
@ -10,9 +9,6 @@
const component = getContext("component")
setContext("screenslot", true)
const loading = writable(false)
setContext("loading", loading)
// Only wrap this as an array to take advantage of svelte keying,
// to ensure the svelte-spa-router is fully remounted when route config
// changes

View file

@ -3,12 +3,13 @@
import { builderStore } from "stores"
const component = getContext("component")
const { styleable } = getContext("sdk")
$: requiredSetting = $component.missingRequiredSettings?.[0]
</script>
{#if $builderStore.inBuilder && requiredSetting}
<div class="component-placeholder">
<div class="component-placeholder" use:styleable={$component.styles}>
<span>
Add the <mark>{requiredSetting.label}</mark> setting to start using your component
-
@ -32,7 +33,7 @@
}
.component-placeholder mark {
background-color: var(--spectrum-global-color-gray-400);
padding: 0 2px;
padding: 0 4px;
border-radius: 2px;
}
.component-placeholder .spectrum-Link {

View file

@ -1,7 +1,6 @@
<script>
import { writable } from "svelte/store"
import { setContext, getContext } from "svelte"
import { Pagination } from "@budibase/bbui"
import { getContext } from "svelte"
import { Pagination, ProgressCircle } from "@budibase/bbui"
import { fetchData, LuceneUtils } from "@budibase/frontend-core"
export let dataSource
@ -14,11 +13,6 @@
const { styleable, Provider, ActionTypes, API } = getContext("sdk")
const component = getContext("component")
// Update loading state
const parentLoading = getContext("loading")
const loading = writable(true)
setContext("loading", loading)
// We need to manage our lucene query manually as we want to allow components
// to extend it
let queryExtensions = {}
@ -26,8 +20,8 @@
$: query = extendQuery(defaultQuery, queryExtensions)
// Fetch data and refresh when needed
$: fetch = createFetch(dataSource, $parentLoading)
$: updateFetch({
$: fetch = createFetch(dataSource)
$: fetch.update({
query,
sortColumn,
sortOrder,
@ -35,9 +29,6 @@
paginate,
})
// Keep loading context updated
$: loading.set($parentLoading || !$fetch.loaded)
// Build our action context
$: actions = [
{
@ -89,18 +80,7 @@
limit,
}
const createFetch = (datasource, parentLoading) => {
// Return a dummy fetch if parent is still loading. We do this so that we
// can still properly subscribe to a valid fetch object and check all
// properties, but we want to avoid fetching the real data until all parents
// have finished loading.
// This logic is only needed due to skeleton loaders, as previously we
// simply blocked component rendering until data was ready.
if (parentLoading) {
return fetchData({ API })
}
// Otherwise return the real thing
const createFetch = datasource => {
return fetchData({
API,
datasource,
@ -114,14 +94,6 @@
})
}
const updateFetch = opts => {
// Only update fetch if parents have stopped loading. Otherwise we will
// trigger a fetch of the real data before parents are ready.
if (!$parentLoading) {
fetch.update(opts)
}
}
const addQueryExtension = (key, extension) => {
if (!key || !extension) {
return
@ -155,17 +127,23 @@
<div use:styleable={$component.styles} class="container">
<Provider {actions} data={dataContext}>
<slot />
{#if paginate && $fetch.supportsPagination}
<div class="pagination">
<Pagination
page={$fetch.pageNumber + 1}
hasPrevPage={$fetch.hasPrevPage}
hasNextPage={$fetch.hasNextPage}
goToPrevPage={fetch.prevPage}
goToNextPage={fetch.nextPage}
/>
{#if !$fetch.loaded}
<div class="loading">
<ProgressCircle />
</div>
{:else}
<slot />
{#if paginate && $fetch.supportsPagination}
<div class="pagination">
<Pagination
page={$fetch.pageNumber + 1}
hasPrevPage={$fetch.hasPrevPage}
hasNextPage={$fetch.hasNextPage}
goToPrevPage={fetch.prevPage}
goToNextPage={fetch.nextPage}
/>
</div>
{/if}
{/if}
</Provider>
</div>
@ -177,6 +155,13 @@
justify-content: flex-start;
align-items: stretch;
}
.loading {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 100px;
}
.pagination {
display: flex;
flex-direction: row;

View file

@ -12,25 +12,22 @@
const { Provider } = getContext("sdk")
const component = getContext("component")
const loading = getContext("loading")
// If the parent DataProvider is loading, fill the rows array with a number of empty objects corresponding to the DataProvider's page size; this allows skeleton loader components to be rendered further down the tree.
$: rows = $loading
? new Array(dataProvider.limit > 20 ? 20 : dataProvider.limit).fill({})
: dataProvider?.rows
$: rows = dataProvider?.rows ?? []
$: loaded = dataProvider?.loaded ?? true
</script>
<Container {direction} {hAlign} {vAlign} {gap} wrap>
{#if $component.empty}
<Placeholder />
{:else if !$loading && rows.length === 0}
<div class="noRows"><i class="ri-list-check-2" />{noRowsMessage}</div>
{:else}
{:else if rows.length > 0}
{#each rows as row, index}
<Provider data={{ ...row, index }}>
<slot />
</Provider>
{/each}
{:else if loaded && noRowsMessage}
<div class="noRows"><i class="ri-list-check-2" />{noRowsMessage}</div>
{/if}
</Container>

View file

@ -1,31 +0,0 @@
<script>
import { getContext } from "svelte"
import { Skeleton } from "@budibase/bbui"
const { styleable } = getContext("sdk")
const component = getContext("component")
export let height
export let width
let styles
$: {
styles = JSON.parse(JSON.stringify($component.styles))
if (!styles.normal.height && height) {
// The height and width props provided to this component can either be numbers or strings set by users (ex. '100%', '100px', '100'). A string of '100' wouldn't be a valid CSS property, but some of our components respect that input, so we need to handle it here also, hence the `!isNaN` check.
styles.normal.height = !isNaN(height) ? `${height}px` : height
}
if (!styles.normal.width && width) {
styles.normal.width = !isNaN(width) ? `${width}px` : width
}
}
</script>
<div use:styleable={styles}>
<Skeleton>
<slot />
</Skeleton>
</div>

View file

@ -37,6 +37,7 @@
let repeaterId
let schema
let enrichedSearchColumns
let schemaLoaded = false
$: fetchSchema(dataSource)
$: enrichSearchColumns(searchColumns, schema).then(
@ -77,135 +78,138 @@
enrichRelationships: true,
})
}
schemaLoaded = true
}
</script>
<Block>
<BlockComponent
type="form"
bind:id={formId}
props={{ dataSource, disableValidation: true }}
>
{#if title || enrichedSearchColumns?.length || showTitleButton}
<BlockComponent
type="container"
props={{
direction: "row",
hAlign: "stretch",
vAlign: "middle",
gap: "M",
wrap: true,
}}
styles={{
normal: {
"margin-bottom": "20px",
},
}}
order={0}
>
<BlockComponent
type="heading"
props={{
text: title,
}}
order={0}
/>
{#if schemaLoaded}
<Block>
<BlockComponent
type="form"
bind:id={formId}
props={{ dataSource, disableValidation: true }}
>
{#if title || enrichedSearchColumns?.length || showTitleButton}
<BlockComponent
type="container"
props={{
direction: "row",
hAlign: "left",
hAlign: "stretch",
vAlign: "middle",
gap: "M",
wrap: true,
}}
order={1}
>
{#if enrichedSearchColumns?.length}
{#each enrichedSearchColumns as column, idx}
<BlockComponent
type={column.componentType}
props={{
field: column.name,
placeholder: column.name,
text: column.name,
autoWidth: true,
}}
order={idx}
styles={{
normal: {
width: "192px",
},
}}
/>
{/each}
{/if}
{#if showTitleButton}
<BlockComponent
type="button"
props={{
onClick: titleButtonAction,
text: titleButtonText,
type: "cta",
}}
order={enrichedSearchColumns?.length ?? 0}
/>
{/if}
</BlockComponent>
</BlockComponent>
{/if}
<BlockComponent
type="dataprovider"
bind:id={dataProviderId}
props={{
dataSource,
filter: enrichedFilter,
sortColumn,
sortOrder,
paginate,
limit,
}}
order={1}
>
<BlockComponent
type="repeater"
bind:id={repeaterId}
context="repeater"
props={{
dataProvider: `{{ literal ${safe(dataProviderId)} }}`,
direction: "row",
hAlign: "stretch",
vAlign: "top",
gap: "M",
noRowsMessage: "No rows found",
}}
styles={{
custom: `display: grid;\ngrid-template-columns: repeat(auto-fill, minmax(min(${cardWidth}px, 100%), 1fr));`,
}}
order={0}
>
<BlockComponent
type="spectrumcard"
props={{
title: cardTitle,
subtitle: cardSubtitle,
description: cardDescription,
imageURL: cardImageURL,
horizontal: cardHorizontal,
showButton: showCardButton,
buttonText: cardButtonText,
buttonOnClick: cardButtonOnClick,
linkURL: fullCardURL,
linkPeek: cardPeek,
}}
styles={{
normal: {
width: "auto",
"margin-bottom": "20px",
},
}}
order={0}
/>
>
<BlockComponent
type="heading"
props={{
text: title,
}}
order={0}
/>
<BlockComponent
type="container"
props={{
direction: "row",
hAlign: "left",
vAlign: "middle",
gap: "M",
wrap: true,
}}
order={1}
>
{#if enrichedSearchColumns?.length}
{#each enrichedSearchColumns as column, idx}
<BlockComponent
type={column.componentType}
props={{
field: column.name,
placeholder: column.name,
text: column.name,
autoWidth: true,
}}
order={idx}
styles={{
normal: {
width: "192px",
},
}}
/>
{/each}
{/if}
{#if showTitleButton}
<BlockComponent
type="button"
props={{
onClick: titleButtonAction,
text: titleButtonText,
type: "cta",
}}
order={enrichedSearchColumns?.length ?? 0}
/>
{/if}
</BlockComponent>
</BlockComponent>
{/if}
<BlockComponent
type="dataprovider"
bind:id={dataProviderId}
props={{
dataSource,
filter: enrichedFilter,
sortColumn,
sortOrder,
paginate,
limit,
}}
order={1}
>
<BlockComponent
type="repeater"
bind:id={repeaterId}
context="repeater"
props={{
dataProvider: `{{ literal ${safe(dataProviderId)} }}`,
direction: "row",
hAlign: "stretch",
vAlign: "top",
gap: "M",
noRowsMessage: "No rows found",
}}
styles={{
custom: `display: grid;\ngrid-template-columns: repeat(auto-fill, minmax(min(${cardWidth}px, 100%), 1fr));`,
}}
order={0}
>
<BlockComponent
type="spectrumcard"
props={{
title: cardTitle,
subtitle: cardSubtitle,
description: cardDescription,
imageURL: cardImageURL,
horizontal: cardHorizontal,
showButton: showCardButton,
buttonText: cardButtonText,
buttonOnClick: cardButtonOnClick,
linkURL: fullCardURL,
linkPeek: cardPeek,
}}
styles={{
normal: {
width: "auto",
},
}}
order={0}
/>
</BlockComponent>
</BlockComponent>
</BlockComponent>
</BlockComponent>
</Block>
</Block>
{/if}

View file

@ -37,6 +37,7 @@
let schema
let primaryDisplay
let enrichedSearchColumns
let schemaLoaded = false
$: fetchSchema(dataSource)
$: enrichSearchColumns(searchColumns, schema).then(
@ -91,6 +92,7 @@
enrichRelationships: true,
})
}
schemaLoaded = true
}
const getNormalFields = schema => {
@ -114,160 +116,162 @@
}
</script>
<Block>
<BlockComponent
type="form"
bind:id={formId}
props={{
dataSource,
disableValidation: true,
editAutoColumns: true,
size,
}}
>
{#if title || enrichedSearchColumns?.length || showTitleButton}
<BlockComponent
type="container"
props={{
direction: "row",
hAlign: "stretch",
vAlign: "middle",
gap: "M",
wrap: true,
}}
styles={{
normal: {
"margin-bottom": "20px",
},
}}
order={0}
>
<BlockComponent
type="heading"
props={{
text: title,
}}
order={0}
/>
{#if schemaLoaded}
<Block>
<BlockComponent
type="form"
bind:id={formId}
props={{
dataSource,
disableValidation: true,
editAutoColumns: true,
size,
}}
>
{#if title || enrichedSearchColumns?.length || showTitleButton}
<BlockComponent
type="container"
props={{
direction: "row",
hAlign: "left",
vAlign: "center",
hAlign: "stretch",
vAlign: "middle",
gap: "M",
wrap: true,
}}
order={1}
styles={{
normal: {
"margin-bottom": "20px",
},
}}
order={0}
>
{#if enrichedSearchColumns?.length}
{#each enrichedSearchColumns as column, idx}
<BlockComponent
type="heading"
props={{
text: title,
}}
order={0}
/>
<BlockComponent
type="container"
props={{
direction: "row",
hAlign: "left",
vAlign: "center",
gap: "M",
wrap: true,
}}
order={1}
>
{#if enrichedSearchColumns?.length}
{#each enrichedSearchColumns as column, idx}
<BlockComponent
type={column.componentType}
props={{
field: column.name,
placeholder: column.name,
text: column.name,
autoWidth: true,
}}
styles={{
normal: {
width: "192px",
},
}}
order={idx}
/>
{/each}
{/if}
{#if showTitleButton}
<BlockComponent
type={column.componentType}
type="button"
props={{
field: column.name,
placeholder: column.name,
text: column.name,
autoWidth: true,
onClick: buttonClickActions,
text: titleButtonText,
type: "cta",
}}
styles={{
normal: {
width: "192px",
},
}}
order={idx}
order={enrichedSearchColumns?.length ?? 0}
/>
{/each}
{/if}
{#if showTitleButton}
<BlockComponent
type="button"
props={{
onClick: buttonClickActions,
text: titleButtonText,
type: "cta",
}}
order={enrichedSearchColumns?.length ?? 0}
/>
{/if}
{/if}
</BlockComponent>
</BlockComponent>
</BlockComponent>
{/if}
<BlockComponent
type="dataprovider"
bind:id={dataProviderId}
props={{
dataSource,
filter: enrichedFilter,
sortColumn: sortColumn || primaryDisplay,
sortOrder,
paginate,
limit: rowCount,
}}
order={1}
>
{/if}
<BlockComponent
type="table"
context="table"
type="dataprovider"
bind:id={dataProviderId}
props={{
dataProvider: `{{ literal ${safe(dataProviderId)} }}`,
columns: tableColumns,
rowCount,
quiet,
compact,
allowSelectRows,
size,
onClick: rowClickActions,
dataSource,
filter: enrichedFilter,
sortColumn: sortColumn || primaryDisplay,
sortOrder,
paginate,
limit: rowCount,
}}
/>
order={1}
>
<BlockComponent
type="table"
context="table"
props={{
dataProvider: `{{ literal ${safe(dataProviderId)} }}`,
columns: tableColumns,
rowCount,
quiet,
compact,
allowSelectRows,
size,
onClick: rowClickActions,
}}
/>
</BlockComponent>
{#if clickBehaviour === "details"}
<BlockComponent
name="Details side panel"
type="sidepanel"
bind:id={detailsSidePanelId}
context="details-side-panel"
order={2}
>
<BlockComponent
name="Details form block"
type="formblock"
bind:id={detailsFormBlockId}
props={{
dataSource,
showSaveButton: true,
showDeleteButton: true,
actionType: "Update",
rowId: `{{ ${safe("state")}.${safe(stateKey)} }}`,
fields: normalFields,
title: editTitle,
labelPosition: "left",
}}
/>
</BlockComponent>
{/if}
{#if showTitleButton && titleButtonClickBehaviour === "new"}
<BlockComponent
name="New row side panel"
type="sidepanel"
bind:id={newRowSidePanelId}
context="new-side-panel"
order={3}
>
<BlockComponent
name="New row form block"
type="formblock"
props={{
dataSource,
showSaveButton: true,
showDeleteButton: false,
actionType: "Create",
fields: normalFields,
title: "Create Row",
labelPosition: "left",
}}
/>
</BlockComponent>
{/if}
</BlockComponent>
{#if clickBehaviour === "details"}
<BlockComponent
name="Details side panel"
type="sidepanel"
bind:id={detailsSidePanelId}
context="details-side-panel"
order={2}
>
<BlockComponent
name="Details form block"
type="formblock"
bind:id={detailsFormBlockId}
props={{
dataSource,
showSaveButton: true,
showDeleteButton: true,
actionType: "Update",
rowId: `{{ ${safe("state")}.${safe(stateKey)} }}`,
fields: normalFields,
title: editTitle,
labelPosition: "left",
}}
/>
</BlockComponent>
{/if}
{#if showTitleButton && titleButtonClickBehaviour === "new"}
<BlockComponent
name="New row side panel"
type="sidepanel"
bind:id={newRowSidePanelId}
context="new-side-panel"
order={3}
>
<BlockComponent
name="New row form block"
type="formblock"
props={{
dataSource,
showSaveButton: true,
showDeleteButton: false,
actionType: "Create",
fields: normalFields,
title: "Create Row",
labelPosition: "left",
}}
/>
</BlockComponent>
{/if}
</BlockComponent>
</Block>
</Block>
{/if}

View file

@ -1,7 +1,6 @@
<script>
import Placeholder from "../Placeholder.svelte"
import FieldGroupFallback from "./FieldGroupFallback.svelte"
import Skeleton from "../Skeleton.svelte"
import { getContext, onDestroy } from "svelte"
export let label
@ -54,8 +53,6 @@
builderStore.actions.updateProp("label", e.target.textContent)
}
const loading = getContext("loading")
onDestroy(() => {
fieldApi?.deregister()
unsubscribe?.()
@ -79,10 +76,6 @@
<div class="spectrum-Form-itemField">
{#if !formContext}
<Placeholder text="Form components need to be wrapped in a form" />
{:else if $loading}
<Skeleton>
<slot />
</Skeleton>
{:else if !fieldState}
<Placeholder />
{:else if schemaType && schemaType !== type && !["options", "longform"].includes(type)}

View file

@ -1,8 +1,7 @@
<script>
import { getContext, setContext } from "svelte"
import { getContext } from "svelte"
import InnerForm from "./InnerForm.svelte"
import { Helpers } from "@budibase/bbui"
import { writable } from "svelte/store"
export let dataSource
export let theme
@ -21,11 +20,6 @@
const context = getContext("context")
const { API, fetchDatasourceSchema } = getContext("sdk")
// Forms also use loading context as they require loading a schema
const parentLoading = getContext("loading")
const loading = writable(true)
setContext("loading", loading)
let loaded = false
let schema
let table
@ -36,7 +30,6 @@
$: resetKey = Helpers.hashString(
schemaKey + JSON.stringify(initialValues) + disabled
)
$: loading.set($parentLoading || !loaded)
// Returns the closes data context which isn't a built in context
const getInitialValues = (type, dataSource, context) => {
@ -86,19 +79,21 @@
}
</script>
{#key resetKey}
<InnerForm
{dataSource}
{theme}
{size}
{disabled}
{actionType}
{schema}
{table}
{initialValues}
{disableValidation}
{editAutoColumns}
>
<slot />
</InnerForm>
{/key}
{#if loaded}
{#key resetKey}
<InnerForm
{dataSource}
{theme}
{size}
{disabled}
{actionType}
{schema}
{table}
{initialValues}
{disableValidation}
{editAutoColumns}
>
<slot />
</InnerForm>
{/key}
{/if}

View file

@ -1,6 +1,6 @@
<script>
import { getContext } from "svelte"
import { Table, Skeleton } from "@budibase/bbui"
import { Table } from "@budibase/bbui"
import SlotRenderer from "./SlotRenderer.svelte"
import { UnsortableTypes } from "../../../constants"
import { onDestroy } from "svelte"
@ -14,7 +14,6 @@
export let compact
export let onClick
const loading = getContext("loading")
const component = getContext("component")
const { styleable, getAction, ActionTypes, rowSelectionStore } =
getContext("sdk")
@ -29,6 +28,7 @@
let selectedRows = []
$: hasChildren = $component.children
$: loading = dataProvider?.loading ?? false
$: data = dataProvider?.rows || []
$: fullSchema = dataProvider?.schema ?? {}
$: fields = getFields(fullSchema, columns, false)
@ -130,7 +130,7 @@
<Table
{data}
{schema}
loading={$loading}
{loading}
{rowCount}
{quiet}
{compact}
@ -145,9 +145,6 @@
on:sort={onSort}
on:click={handleClick}
>
<div class="skeleton" slot="loadingIndicator">
<Skeleton />
</div>
<slot />
</Table>
{#if allowSelectRows && selectedRows.length}
@ -161,12 +158,6 @@
div {
background-color: var(--spectrum-alias-background-color-secondary);
}
.skeleton {
height: 100%;
width: 100%;
}
.row-count {
margin-top: var(--spacing-l);
}

View file

@ -1,13 +1,13 @@
{
"name": "@budibase/frontend-core",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase",
"license": "MPL-2.0",
"svelte": "src/index.js",
"dependencies": {
"@budibase/bbui": "2.4.27-alpha.5",
"@budibase/shared-core": "2.4.27-alpha.5",
"@budibase/bbui": "2.4.27-alpha.6",
"@budibase/shared-core": "2.4.27-alpha.6",
"lodash": "^4.17.21",
"svelte": "^3.46.2"
}

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/sdk",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Budibase Public API SDK",
"author": "Budibase",
"license": "MPL-2.0",

View file

@ -1,7 +1,7 @@
{
"name": "@budibase/server",
"email": "hi@budibase.com",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Budibase Web Server",
"main": "src/index.ts",
"repository": {
@ -43,12 +43,12 @@
"license": "GPL-3.0",
"dependencies": {
"@apidevtools/swagger-parser": "10.0.3",
"@budibase/backend-core": "2.4.27-alpha.5",
"@budibase/client": "2.4.27-alpha.5",
"@budibase/pro": "2.4.27-alpha.5",
"@budibase/shared-core": "2.4.27-alpha.5",
"@budibase/string-templates": "2.4.27-alpha.5",
"@budibase/types": "2.4.27-alpha.5",
"@budibase/backend-core": "2.4.27-alpha.6",
"@budibase/client": "2.4.27-alpha.6",
"@budibase/pro": "2.4.27-alpha.6",
"@budibase/shared-core": "2.4.27-alpha.6",
"@budibase/string-templates": "2.4.27-alpha.6",
"@budibase/types": "2.4.27-alpha.6",
"@bull-board/api": "3.7.0",
"@bull-board/koa": "3.9.4",
"@elastic/elasticsearch": "7.10.0",

View file

@ -1278,14 +1278,14 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@2.4.27-alpha.5":
version "2.4.27-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.27-alpha.5.tgz#08a1ba72b6aee4ac05c71292c010f6b90a0c164e"
integrity sha512-Q7ooVt3PPcjZU7i8HKaDOoURp0MLSjO1WRTFe+bQteGv1V1Hw6twzM4bmr7u4AswF/kP1tpwx36EQoDr50SfyQ==
"@budibase/backend-core@2.4.27-alpha.6":
version "2.4.27-alpha.6"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.27-alpha.6.tgz#8105c400fd0a3fa6264d95e9b99c712e84a07007"
integrity sha512-an+r4AMNhxPUJGxokA/W1PvUsdYih14QcQLfN3Howd0A6h4PZaHpjTC/6xmdDNv0XUcDZ8l8LkAoaW/kMLJG3Q==
dependencies:
"@budibase/nano" "10.1.2"
"@budibase/pouchdb-replication-stream" "1.2.10"
"@budibase/types" "2.4.27-alpha.5"
"@budibase/types" "2.4.27-alpha.6"
"@shopify/jest-koa-mocks" "5.0.1"
"@techpass/passport-openidconnect" "0.3.2"
aws-cloudfront-sign "2.2.0"
@ -1417,14 +1417,14 @@
pouchdb-promise "^6.0.4"
through2 "^2.0.0"
"@budibase/pro@2.4.27-alpha.5":
version "2.4.27-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.27-alpha.5.tgz#c7d4bd5feefe5184dc5f78aa840a9f2a06809190"
integrity sha512-XLuW7Giz21A9yMPzIRsgEbc7wUVLDw3yeNhM0BmgUbEjB3N5XLMrJlCLf/XrKYzRBHeZN25EX34Sa7ZthdqELA==
"@budibase/pro@2.4.27-alpha.6":
version "2.4.27-alpha.6"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.27-alpha.6.tgz#2184aea5e640a2abf4a8803a4acac0b5516a8b01"
integrity sha512-gAxuZnfEo1z65Zuf8S9g7qDrrJOVkayKw2GbdX6pbZ1dJbKDu6N3WDJjWfkyLFAOLu4Oy1XtOsHX8AobHZ42xQ==
dependencies:
"@budibase/backend-core" "2.4.27-alpha.5"
"@budibase/backend-core" "2.4.27-alpha.6"
"@budibase/string-templates" "2.3.20"
"@budibase/types" "2.4.27-alpha.5"
"@budibase/types" "2.4.27-alpha.6"
"@koa/router" "8.0.8"
bull "4.10.1"
joi "17.6.0"
@ -1463,10 +1463,10 @@
lodash "^4.17.20"
vm2 "^3.9.4"
"@budibase/types@2.4.27-alpha.5":
version "2.4.27-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.27-alpha.5.tgz#710f773d09be39a83f9ee8728d77ea1d457d0d0a"
integrity sha512-uKD+1CnxDgtO+cvtPi56jkIzRZ6O+MZmQQcGwxg/pAKHCm45puaygbKb/+yfJLGVabzohMUuWST/Q6ay3RuJmQ==
"@budibase/types@2.4.27-alpha.6":
version "2.4.27-alpha.6"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.27-alpha.6.tgz#9235b86764e4c837bab45779a9596233662de8be"
integrity sha512-4+b3NKiqOndNjmzsgr1mZvt4VFhkRVlyMTss9Iu0T4o9SBW20GhJa6iWkiypqHiA50uGDAzgA2u2n/5m59aMyA==
"@bull-board/api@3.7.0":
version "3.7.0"

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/shared-core",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Shared data utils",
"main": "dist/cjs/src/index.js",
"types": "dist/mjs/src/index.d.ts",
@ -20,7 +20,7 @@
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
},
"dependencies": {
"@budibase/types": "2.4.27-alpha.5"
"@budibase/types": "2.4.27-alpha.6"
},
"devDependencies": {
"concurrently": "^7.6.0",

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/string-templates",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"module": "dist/bundle.mjs",

View file

@ -1,6 +1,6 @@
{
"name": "@budibase/types",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Budibase types",
"main": "dist/cjs/index.js",
"types": "dist/mjs/index.d.ts",

View file

@ -1,7 +1,7 @@
{
"name": "@budibase/worker",
"email": "hi@budibase.com",
"version": "2.4.27-alpha.5",
"version": "2.4.27-alpha.6",
"description": "Budibase background service",
"main": "src/index.ts",
"repository": {
@ -36,10 +36,10 @@
"author": "Budibase",
"license": "GPL-3.0",
"dependencies": {
"@budibase/backend-core": "2.4.27-alpha.5",
"@budibase/pro": "2.4.27-alpha.5",
"@budibase/string-templates": "2.4.27-alpha.5",
"@budibase/types": "2.4.27-alpha.5",
"@budibase/backend-core": "2.4.27-alpha.6",
"@budibase/pro": "2.4.27-alpha.6",
"@budibase/string-templates": "2.4.27-alpha.6",
"@budibase/types": "2.4.27-alpha.6",
"@koa/router": "8.0.8",
"@sentry/node": "6.17.7",
"@techpass/passport-openidconnect": "0.3.2",

View file

@ -475,14 +475,14 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@2.4.27-alpha.5":
version "2.4.27-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.27-alpha.5.tgz#08a1ba72b6aee4ac05c71292c010f6b90a0c164e"
integrity sha512-Q7ooVt3PPcjZU7i8HKaDOoURp0MLSjO1WRTFe+bQteGv1V1Hw6twzM4bmr7u4AswF/kP1tpwx36EQoDr50SfyQ==
"@budibase/backend-core@2.4.27-alpha.6":
version "2.4.27-alpha.6"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.27-alpha.6.tgz#8105c400fd0a3fa6264d95e9b99c712e84a07007"
integrity sha512-an+r4AMNhxPUJGxokA/W1PvUsdYih14QcQLfN3Howd0A6h4PZaHpjTC/6xmdDNv0XUcDZ8l8LkAoaW/kMLJG3Q==
dependencies:
"@budibase/nano" "10.1.2"
"@budibase/pouchdb-replication-stream" "1.2.10"
"@budibase/types" "2.4.27-alpha.5"
"@budibase/types" "2.4.27-alpha.6"
"@shopify/jest-koa-mocks" "5.0.1"
"@techpass/passport-openidconnect" "0.3.2"
aws-cloudfront-sign "2.2.0"
@ -564,14 +564,14 @@
pouchdb-promise "^6.0.4"
through2 "^2.0.0"
"@budibase/pro@2.4.27-alpha.5":
version "2.4.27-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.27-alpha.5.tgz#c7d4bd5feefe5184dc5f78aa840a9f2a06809190"
integrity sha512-XLuW7Giz21A9yMPzIRsgEbc7wUVLDw3yeNhM0BmgUbEjB3N5XLMrJlCLf/XrKYzRBHeZN25EX34Sa7ZthdqELA==
"@budibase/pro@2.4.27-alpha.6":
version "2.4.27-alpha.6"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.27-alpha.6.tgz#2184aea5e640a2abf4a8803a4acac0b5516a8b01"
integrity sha512-gAxuZnfEo1z65Zuf8S9g7qDrrJOVkayKw2GbdX6pbZ1dJbKDu6N3WDJjWfkyLFAOLu4Oy1XtOsHX8AobHZ42xQ==
dependencies:
"@budibase/backend-core" "2.4.27-alpha.5"
"@budibase/backend-core" "2.4.27-alpha.6"
"@budibase/string-templates" "2.3.20"
"@budibase/types" "2.4.27-alpha.5"
"@budibase/types" "2.4.27-alpha.6"
"@koa/router" "8.0.8"
bull "4.10.1"
joi "17.6.0"
@ -592,10 +592,10 @@
lodash "^4.17.20"
vm2 "^3.9.4"
"@budibase/types@2.4.27-alpha.5":
version "2.4.27-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.27-alpha.5.tgz#710f773d09be39a83f9ee8728d77ea1d457d0d0a"
integrity sha512-uKD+1CnxDgtO+cvtPi56jkIzRZ6O+MZmQQcGwxg/pAKHCm45puaygbKb/+yfJLGVabzohMUuWST/Q6ay3RuJmQ==
"@budibase/types@2.4.27-alpha.6":
version "2.4.27-alpha.6"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.27-alpha.6.tgz#9235b86764e4c837bab45779a9596233662de8be"
integrity sha512-4+b3NKiqOndNjmzsgr1mZvt4VFhkRVlyMTss9Iu0T4o9SBW20GhJa6iWkiypqHiA50uGDAzgA2u2n/5m59aMyA==
"@cspotcode/source-map-support@^0.8.0":
version "0.8.1"