Revert skeleton loaders and restore required setting functionality (#9979)
This commit is contained in:
parent
05ba08a956
commit
1b2b4dba88
|
@ -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>
|
|
|
@ -4,7 +4,6 @@ import "./bbui.css"
|
||||||
import "@spectrum-css/icon/dist/index-vars.css"
|
import "@spectrum-css/icon/dist/index-vars.css"
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
export { default as Skeleton } from "./Skeleton/Skeleton.svelte"
|
|
||||||
export { default as Input } from "./Form/Input.svelte"
|
export { default as Input } from "./Form/Input.svelte"
|
||||||
export { default as Stepper } from "./Form/Stepper.svelte"
|
export { default as Stepper } from "./Form/Stepper.svelte"
|
||||||
export { default as TextArea } from "./Form/TextArea.svelte"
|
export { default as TextArea } from "./Form/TextArea.svelte"
|
||||||
|
|
|
@ -2346,7 +2346,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"stringfield": {
|
"stringfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Text Field",
|
"name": "Text Field",
|
||||||
"icon": "Text",
|
"icon": "Text",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -2436,7 +2435,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"numberfield": {
|
"numberfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Number Field",
|
"name": "Number Field",
|
||||||
"icon": "123",
|
"icon": "123",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -2492,7 +2490,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"passwordfield": {
|
"passwordfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Password Field",
|
"name": "Password Field",
|
||||||
"icon": "LockClosed",
|
"icon": "LockClosed",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -2548,7 +2545,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"optionsfield": {
|
"optionsfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Options Picker",
|
"name": "Options Picker",
|
||||||
"icon": "Menu",
|
"icon": "Menu",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -2715,7 +2711,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"multifieldselect": {
|
"multifieldselect": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Multi-select Picker",
|
"name": "Multi-select Picker",
|
||||||
"icon": "ViewList",
|
"icon": "ViewList",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -2876,7 +2871,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"booleanfield": {
|
"booleanfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Checkbox",
|
"name": "Checkbox",
|
||||||
"icon": "SelectBox",
|
"icon": "SelectBox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
|
@ -2955,7 +2949,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"longformfield": {
|
"longformfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Long Form Field",
|
"name": "Long Form Field",
|
||||||
"icon": "TextAlignLeft",
|
"icon": "TextAlignLeft",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -3033,7 +3026,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"datetimefield": {
|
"datetimefield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Date Picker",
|
"name": "Date Picker",
|
||||||
"icon": "Date",
|
"icon": "Date",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -3113,7 +3105,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"codescanner": {
|
"codescanner": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Barcode/QR Scanner",
|
"name": "Barcode/QR Scanner",
|
||||||
"icon": "Camera",
|
"icon": "Camera",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -3275,7 +3266,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"attachmentfield": {
|
"attachmentfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Attachment",
|
"name": "Attachment",
|
||||||
"icon": "Attach",
|
"icon": "Attach",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -3338,7 +3328,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"relationshipfield": {
|
"relationshipfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Relationship Picker",
|
"name": "Relationship Picker",
|
||||||
"icon": "TaskList",
|
"icon": "TaskList",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -3400,7 +3389,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"jsonfield": {
|
"jsonfield": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "JSON Field",
|
"name": "JSON Field",
|
||||||
"icon": "Brackets",
|
"icon": "Brackets",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
|
@ -3591,7 +3579,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"skeleton": false,
|
|
||||||
"name": "Table",
|
"name": "Table",
|
||||||
"icon": "Table",
|
"icon": "Table",
|
||||||
"illegalChildren": ["section"],
|
"illegalChildren": ["section"],
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
// to render this part of the block, taking advantage of binding enrichment
|
// to render this part of the block, taking advantage of binding enrichment
|
||||||
$: id = `${block.id}-${context ?? rand}`
|
$: id = `${block.id}-${context ?? rand}`
|
||||||
$: instance = {
|
$: instance = {
|
||||||
_blockElementHasChildren: $$slots?.default ?? false,
|
|
||||||
_component: `@budibase/standard-components/${type}`,
|
_component: `@budibase/standard-components/${type}`,
|
||||||
_id: id,
|
_id: id,
|
||||||
_instanceName: name || type[0].toUpperCase() + type.slice(1),
|
_instanceName: name || type[0].toUpperCase() + type.slice(1),
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
import Placeholder from "components/app/Placeholder.svelte"
|
import Placeholder from "components/app/Placeholder.svelte"
|
||||||
import ScreenPlaceholder from "components/app/ScreenPlaceholder.svelte"
|
import ScreenPlaceholder from "components/app/ScreenPlaceholder.svelte"
|
||||||
import ComponentPlaceholder from "components/app/ComponentPlaceholder.svelte"
|
import ComponentPlaceholder from "components/app/ComponentPlaceholder.svelte"
|
||||||
import Skeleton from "components/app/Skeleton.svelte"
|
|
||||||
|
|
||||||
export let instance = {}
|
export let instance = {}
|
||||||
export let isLayout = false
|
export let isLayout = false
|
||||||
|
@ -39,7 +38,6 @@
|
||||||
|
|
||||||
// Get parent contexts
|
// Get parent contexts
|
||||||
const context = getContext("context")
|
const context = getContext("context")
|
||||||
const loading = getContext("loading")
|
|
||||||
const insideScreenslot = !!getContext("screenslot")
|
const insideScreenslot = !!getContext("screenslot")
|
||||||
|
|
||||||
// Create component context
|
// Create component context
|
||||||
|
@ -172,15 +170,6 @@
|
||||||
$: pad = pad || (interactive && hasChildren && inDndPath)
|
$: pad = pad || (interactive && hasChildren && inDndPath)
|
||||||
$: $dndIsDragging, (pad = false)
|
$: $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
|
// Update component context
|
||||||
$: store.set({
|
$: store.set({
|
||||||
id,
|
id,
|
||||||
|
@ -507,12 +496,7 @@
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showSkeleton}
|
{#if constructor && initialSettings && (visible || inSelectedPath) && !builderHidden}
|
||||||
<Skeleton
|
|
||||||
height={initialSettings?.height || definition?.size?.height || 0}
|
|
||||||
width={initialSettings?.width || definition?.size?.width || 0}
|
|
||||||
/>
|
|
||||||
{:else if constructor && initialSettings && (visible || inSelectedPath) && !builderHidden}
|
|
||||||
<!-- The ID is used as a class because getElementsByClassName is O(1) -->
|
<!-- The ID is used as a class because getElementsByClassName is O(1) -->
|
||||||
<!-- and the performance matters for the selection indicators -->
|
<!-- and the performance matters for the selection indicators -->
|
||||||
<div
|
<div
|
||||||
|
@ -530,23 +514,25 @@
|
||||||
data-icon={icon}
|
data-icon={icon}
|
||||||
data-parent={parent}
|
data-parent={parent}
|
||||||
>
|
>
|
||||||
<svelte:component this={constructor} bind:this={ref} {...initialSettings}>
|
{#if hasMissingRequiredSettings}
|
||||||
{#if hasMissingRequiredSettings}
|
<ComponentPlaceholder />
|
||||||
<ComponentPlaceholder />
|
{:else}
|
||||||
{:else if children.length}
|
<svelte:component this={constructor} bind:this={ref} {...initialSettings}>
|
||||||
{#each children as child (child._id)}
|
{#if children.length}
|
||||||
<svelte:self instance={child} parent={id} />
|
{#each children as child (child._id)}
|
||||||
{/each}
|
<svelte:self instance={child} parent={id} />
|
||||||
{:else if emptyState}
|
{/each}
|
||||||
{#if isScreen}
|
{:else if emptyState}
|
||||||
<ScreenPlaceholder />
|
{#if isScreen}
|
||||||
{:else}
|
<ScreenPlaceholder />
|
||||||
<Placeholder />
|
{:else}
|
||||||
|
<Placeholder />
|
||||||
|
{/if}
|
||||||
|
{:else if isBlock}
|
||||||
|
<slot />
|
||||||
{/if}
|
{/if}
|
||||||
{:else if isBlock}
|
</svelte:component>
|
||||||
<slot />
|
{/if}
|
||||||
{/if}
|
|
||||||
</svelte:component>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
import { writable } from "svelte/store"
|
|
||||||
import { setContext, getContext, onMount } from "svelte"
|
import { setContext, getContext, onMount } from "svelte"
|
||||||
import Router, { querystring } from "svelte-spa-router"
|
import Router, { querystring } from "svelte-spa-router"
|
||||||
import { routeStore, stateStore } from "stores"
|
import { routeStore, stateStore } from "stores"
|
||||||
|
@ -10,9 +9,6 @@
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
setContext("screenslot", true)
|
setContext("screenslot", true)
|
||||||
|
|
||||||
const loading = writable(false)
|
|
||||||
setContext("loading", loading)
|
|
||||||
|
|
||||||
// Only wrap this as an array to take advantage of svelte keying,
|
// Only wrap this as an array to take advantage of svelte keying,
|
||||||
// to ensure the svelte-spa-router is fully remounted when route config
|
// to ensure the svelte-spa-router is fully remounted when route config
|
||||||
// changes
|
// changes
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
import { builderStore } from "stores"
|
import { builderStore } from "stores"
|
||||||
|
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
|
const { styleable } = getContext("sdk")
|
||||||
|
|
||||||
$: requiredSetting = $component.missingRequiredSettings?.[0]
|
$: requiredSetting = $component.missingRequiredSettings?.[0]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $builderStore.inBuilder && requiredSetting}
|
{#if $builderStore.inBuilder && requiredSetting}
|
||||||
<div class="component-placeholder">
|
<div class="component-placeholder" use:styleable={$component.styles}>
|
||||||
<span>
|
<span>
|
||||||
Add the <mark>{requiredSetting.label}</mark> setting to start using your component
|
Add the <mark>{requiredSetting.label}</mark> setting to start using your component
|
||||||
-
|
-
|
||||||
|
@ -32,7 +33,7 @@
|
||||||
}
|
}
|
||||||
.component-placeholder mark {
|
.component-placeholder mark {
|
||||||
background-color: var(--spectrum-global-color-gray-400);
|
background-color: var(--spectrum-global-color-gray-400);
|
||||||
padding: 0 2px;
|
padding: 0 4px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
.component-placeholder .spectrum-Link {
|
.component-placeholder .spectrum-Link {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { writable } from "svelte/store"
|
import { getContext } from "svelte"
|
||||||
import { setContext, getContext } from "svelte"
|
import { Pagination, ProgressCircle } from "@budibase/bbui"
|
||||||
import { Pagination } from "@budibase/bbui"
|
|
||||||
import { fetchData, LuceneUtils } from "@budibase/frontend-core"
|
import { fetchData, LuceneUtils } from "@budibase/frontend-core"
|
||||||
|
|
||||||
export let dataSource
|
export let dataSource
|
||||||
|
@ -14,11 +13,6 @@
|
||||||
const { styleable, Provider, ActionTypes, API } = getContext("sdk")
|
const { styleable, Provider, ActionTypes, API } = getContext("sdk")
|
||||||
const component = getContext("component")
|
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
|
// We need to manage our lucene query manually as we want to allow components
|
||||||
// to extend it
|
// to extend it
|
||||||
let queryExtensions = {}
|
let queryExtensions = {}
|
||||||
|
@ -26,8 +20,8 @@
|
||||||
$: query = extendQuery(defaultQuery, queryExtensions)
|
$: query = extendQuery(defaultQuery, queryExtensions)
|
||||||
|
|
||||||
// Fetch data and refresh when needed
|
// Fetch data and refresh when needed
|
||||||
$: fetch = createFetch(dataSource, $parentLoading)
|
$: fetch = createFetch(dataSource)
|
||||||
$: updateFetch({
|
$: fetch.update({
|
||||||
query,
|
query,
|
||||||
sortColumn,
|
sortColumn,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
|
@ -35,9 +29,6 @@
|
||||||
paginate,
|
paginate,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Keep loading context updated
|
|
||||||
$: loading.set($parentLoading || !$fetch.loaded)
|
|
||||||
|
|
||||||
// Build our action context
|
// Build our action context
|
||||||
$: actions = [
|
$: actions = [
|
||||||
{
|
{
|
||||||
|
@ -89,18 +80,7 @@
|
||||||
limit,
|
limit,
|
||||||
}
|
}
|
||||||
|
|
||||||
const createFetch = (datasource, parentLoading) => {
|
const createFetch = datasource => {
|
||||||
// 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
|
|
||||||
return fetchData({
|
return fetchData({
|
||||||
API,
|
API,
|
||||||
datasource,
|
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) => {
|
const addQueryExtension = (key, extension) => {
|
||||||
if (!key || !extension) {
|
if (!key || !extension) {
|
||||||
return
|
return
|
||||||
|
@ -155,17 +127,23 @@
|
||||||
|
|
||||||
<div use:styleable={$component.styles} class="container">
|
<div use:styleable={$component.styles} class="container">
|
||||||
<Provider {actions} data={dataContext}>
|
<Provider {actions} data={dataContext}>
|
||||||
<slot />
|
{#if !$fetch.loaded}
|
||||||
{#if paginate && $fetch.supportsPagination}
|
<div class="loading">
|
||||||
<div class="pagination">
|
<ProgressCircle />
|
||||||
<Pagination
|
|
||||||
page={$fetch.pageNumber + 1}
|
|
||||||
hasPrevPage={$fetch.hasPrevPage}
|
|
||||||
hasNextPage={$fetch.hasNextPage}
|
|
||||||
goToPrevPage={fetch.prevPage}
|
|
||||||
goToNextPage={fetch.nextPage}
|
|
||||||
/>
|
|
||||||
</div>
|
</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}
|
{/if}
|
||||||
</Provider>
|
</Provider>
|
||||||
</div>
|
</div>
|
||||||
|
@ -177,6 +155,13 @@
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
.pagination {
|
.pagination {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
@ -12,25 +12,22 @@
|
||||||
|
|
||||||
const { Provider } = getContext("sdk")
|
const { Provider } = getContext("sdk")
|
||||||
const component = getContext("component")
|
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 = dataProvider?.rows ?? []
|
||||||
$: rows = $loading
|
$: loaded = dataProvider?.loaded ?? true
|
||||||
? new Array(dataProvider.limit > 20 ? 20 : dataProvider.limit).fill({})
|
|
||||||
: dataProvider?.rows
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Container {direction} {hAlign} {vAlign} {gap} wrap>
|
<Container {direction} {hAlign} {vAlign} {gap} wrap>
|
||||||
{#if $component.empty}
|
{#if $component.empty}
|
||||||
<Placeholder />
|
<Placeholder />
|
||||||
{:else if !$loading && rows.length === 0}
|
{:else if rows.length > 0}
|
||||||
<div class="noRows"><i class="ri-list-check-2" />{noRowsMessage}</div>
|
|
||||||
{:else}
|
|
||||||
{#each rows as row, index}
|
{#each rows as row, index}
|
||||||
<Provider data={{ ...row, index }}>
|
<Provider data={{ ...row, index }}>
|
||||||
<slot />
|
<slot />
|
||||||
</Provider>
|
</Provider>
|
||||||
{/each}
|
{/each}
|
||||||
|
{:else if loaded && noRowsMessage}
|
||||||
|
<div class="noRows"><i class="ri-list-check-2" />{noRowsMessage}</div>
|
||||||
{/if}
|
{/if}
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
|
@ -37,6 +37,7 @@
|
||||||
let repeaterId
|
let repeaterId
|
||||||
let schema
|
let schema
|
||||||
let enrichedSearchColumns
|
let enrichedSearchColumns
|
||||||
|
let schemaLoaded = false
|
||||||
|
|
||||||
$: fetchSchema(dataSource)
|
$: fetchSchema(dataSource)
|
||||||
$: enrichSearchColumns(searchColumns, schema).then(
|
$: enrichSearchColumns(searchColumns, schema).then(
|
||||||
|
@ -77,135 +78,138 @@
|
||||||
enrichRelationships: true,
|
enrichRelationships: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
schemaLoaded = true
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Block>
|
{#if schemaLoaded}
|
||||||
<BlockComponent
|
<Block>
|
||||||
type="form"
|
<BlockComponent
|
||||||
bind:id={formId}
|
type="form"
|
||||||
props={{ dataSource, disableValidation: true }}
|
bind:id={formId}
|
||||||
>
|
props={{ dataSource, disableValidation: true }}
|
||||||
{#if title || enrichedSearchColumns?.length || showTitleButton}
|
>
|
||||||
<BlockComponent
|
{#if title || enrichedSearchColumns?.length || showTitleButton}
|
||||||
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}
|
|
||||||
/>
|
|
||||||
<BlockComponent
|
<BlockComponent
|
||||||
type="container"
|
type="container"
|
||||||
props={{
|
props={{
|
||||||
direction: "row",
|
direction: "row",
|
||||||
hAlign: "left",
|
hAlign: "stretch",
|
||||||
vAlign: "middle",
|
vAlign: "middle",
|
||||||
gap: "M",
|
gap: "M",
|
||||||
wrap: true,
|
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={{
|
styles={{
|
||||||
normal: {
|
normal: {
|
||||||
width: "auto",
|
"margin-bottom": "20px",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
order={0}
|
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>
|
</BlockComponent>
|
||||||
</BlockComponent>
|
</Block>
|
||||||
</Block>
|
{/if}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
let schema
|
let schema
|
||||||
let primaryDisplay
|
let primaryDisplay
|
||||||
let enrichedSearchColumns
|
let enrichedSearchColumns
|
||||||
|
let schemaLoaded = false
|
||||||
|
|
||||||
$: fetchSchema(dataSource)
|
$: fetchSchema(dataSource)
|
||||||
$: enrichSearchColumns(searchColumns, schema).then(
|
$: enrichSearchColumns(searchColumns, schema).then(
|
||||||
|
@ -91,6 +92,7 @@
|
||||||
enrichRelationships: true,
|
enrichRelationships: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
schemaLoaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNormalFields = schema => {
|
const getNormalFields = schema => {
|
||||||
|
@ -114,160 +116,162 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Block>
|
{#if schemaLoaded}
|
||||||
<BlockComponent
|
<Block>
|
||||||
type="form"
|
<BlockComponent
|
||||||
bind:id={formId}
|
type="form"
|
||||||
props={{
|
bind:id={formId}
|
||||||
dataSource,
|
props={{
|
||||||
disableValidation: true,
|
dataSource,
|
||||||
editAutoColumns: true,
|
disableValidation: true,
|
||||||
size,
|
editAutoColumns: true,
|
||||||
}}
|
size,
|
||||||
>
|
}}
|
||||||
{#if title || enrichedSearchColumns?.length || showTitleButton}
|
>
|
||||||
<BlockComponent
|
{#if title || enrichedSearchColumns?.length || showTitleButton}
|
||||||
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}
|
|
||||||
/>
|
|
||||||
<BlockComponent
|
<BlockComponent
|
||||||
type="container"
|
type="container"
|
||||||
props={{
|
props={{
|
||||||
direction: "row",
|
direction: "row",
|
||||||
hAlign: "left",
|
hAlign: "stretch",
|
||||||
vAlign: "center",
|
vAlign: "middle",
|
||||||
gap: "M",
|
gap: "M",
|
||||||
wrap: true,
|
wrap: true,
|
||||||
}}
|
}}
|
||||||
order={1}
|
styles={{
|
||||||
|
normal: {
|
||||||
|
"margin-bottom": "20px",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
order={0}
|
||||||
>
|
>
|
||||||
{#if enrichedSearchColumns?.length}
|
<BlockComponent
|
||||||
{#each enrichedSearchColumns as column, idx}
|
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
|
<BlockComponent
|
||||||
type={column.componentType}
|
type="button"
|
||||||
props={{
|
props={{
|
||||||
field: column.name,
|
onClick: buttonClickActions,
|
||||||
placeholder: column.name,
|
text: titleButtonText,
|
||||||
text: column.name,
|
type: "cta",
|
||||||
autoWidth: true,
|
|
||||||
}}
|
}}
|
||||||
styles={{
|
order={enrichedSearchColumns?.length ?? 0}
|
||||||
normal: {
|
|
||||||
width: "192px",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
order={idx}
|
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/if}
|
||||||
{/if}
|
</BlockComponent>
|
||||||
{#if showTitleButton}
|
|
||||||
<BlockComponent
|
|
||||||
type="button"
|
|
||||||
props={{
|
|
||||||
onClick: buttonClickActions,
|
|
||||||
text: titleButtonText,
|
|
||||||
type: "cta",
|
|
||||||
}}
|
|
||||||
order={enrichedSearchColumns?.length ?? 0}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</BlockComponent>
|
</BlockComponent>
|
||||||
</BlockComponent>
|
{/if}
|
||||||
{/if}
|
|
||||||
<BlockComponent
|
|
||||||
type="dataprovider"
|
|
||||||
bind:id={dataProviderId}
|
|
||||||
props={{
|
|
||||||
dataSource,
|
|
||||||
filter: enrichedFilter,
|
|
||||||
sortColumn: sortColumn || primaryDisplay,
|
|
||||||
sortOrder,
|
|
||||||
paginate,
|
|
||||||
limit: rowCount,
|
|
||||||
}}
|
|
||||||
order={1}
|
|
||||||
>
|
|
||||||
<BlockComponent
|
<BlockComponent
|
||||||
type="table"
|
type="dataprovider"
|
||||||
context="table"
|
bind:id={dataProviderId}
|
||||||
props={{
|
props={{
|
||||||
dataProvider: `{{ literal ${safe(dataProviderId)} }}`,
|
dataSource,
|
||||||
columns: tableColumns,
|
filter: enrichedFilter,
|
||||||
rowCount,
|
sortColumn: sortColumn || primaryDisplay,
|
||||||
quiet,
|
sortOrder,
|
||||||
compact,
|
paginate,
|
||||||
allowSelectRows,
|
limit: rowCount,
|
||||||
size,
|
|
||||||
onClick: rowClickActions,
|
|
||||||
}}
|
}}
|
||||||
/>
|
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>
|
</BlockComponent>
|
||||||
{#if clickBehaviour === "details"}
|
</Block>
|
||||||
<BlockComponent
|
{/if}
|
||||||
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>
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import Placeholder from "../Placeholder.svelte"
|
import Placeholder from "../Placeholder.svelte"
|
||||||
import FieldGroupFallback from "./FieldGroupFallback.svelte"
|
import FieldGroupFallback from "./FieldGroupFallback.svelte"
|
||||||
import Skeleton from "../Skeleton.svelte"
|
|
||||||
import { getContext, onDestroy } from "svelte"
|
import { getContext, onDestroy } from "svelte"
|
||||||
|
|
||||||
export let label
|
export let label
|
||||||
|
@ -54,8 +53,6 @@
|
||||||
builderStore.actions.updateProp("label", e.target.textContent)
|
builderStore.actions.updateProp("label", e.target.textContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
const loading = getContext("loading")
|
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
fieldApi?.deregister()
|
fieldApi?.deregister()
|
||||||
unsubscribe?.()
|
unsubscribe?.()
|
||||||
|
@ -79,10 +76,6 @@
|
||||||
<div class="spectrum-Form-itemField">
|
<div class="spectrum-Form-itemField">
|
||||||
{#if !formContext}
|
{#if !formContext}
|
||||||
<Placeholder text="Form components need to be wrapped in a form" />
|
<Placeholder text="Form components need to be wrapped in a form" />
|
||||||
{:else if $loading}
|
|
||||||
<Skeleton>
|
|
||||||
<slot />
|
|
||||||
</Skeleton>
|
|
||||||
{:else if !fieldState}
|
{:else if !fieldState}
|
||||||
<Placeholder />
|
<Placeholder />
|
||||||
{:else if schemaType && schemaType !== type && !["options", "longform"].includes(type)}
|
{:else if schemaType && schemaType !== type && !["options", "longform"].includes(type)}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext, setContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import InnerForm from "./InnerForm.svelte"
|
import InnerForm from "./InnerForm.svelte"
|
||||||
import { Helpers } from "@budibase/bbui"
|
import { Helpers } from "@budibase/bbui"
|
||||||
import { writable } from "svelte/store"
|
|
||||||
|
|
||||||
export let dataSource
|
export let dataSource
|
||||||
export let theme
|
export let theme
|
||||||
|
@ -21,11 +20,6 @@
|
||||||
const context = getContext("context")
|
const context = getContext("context")
|
||||||
const { API, fetchDatasourceSchema } = getContext("sdk")
|
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 loaded = false
|
||||||
let schema
|
let schema
|
||||||
let table
|
let table
|
||||||
|
@ -36,7 +30,6 @@
|
||||||
$: resetKey = Helpers.hashString(
|
$: resetKey = Helpers.hashString(
|
||||||
schemaKey + JSON.stringify(initialValues) + disabled
|
schemaKey + JSON.stringify(initialValues) + disabled
|
||||||
)
|
)
|
||||||
$: loading.set($parentLoading || !loaded)
|
|
||||||
|
|
||||||
// Returns the closes data context which isn't a built in context
|
// Returns the closes data context which isn't a built in context
|
||||||
const getInitialValues = (type, dataSource, context) => {
|
const getInitialValues = (type, dataSource, context) => {
|
||||||
|
@ -86,19 +79,21 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#key resetKey}
|
{#if loaded}
|
||||||
<InnerForm
|
{#key resetKey}
|
||||||
{dataSource}
|
<InnerForm
|
||||||
{theme}
|
{dataSource}
|
||||||
{size}
|
{theme}
|
||||||
{disabled}
|
{size}
|
||||||
{actionType}
|
{disabled}
|
||||||
{schema}
|
{actionType}
|
||||||
{table}
|
{schema}
|
||||||
{initialValues}
|
{table}
|
||||||
{disableValidation}
|
{initialValues}
|
||||||
{editAutoColumns}
|
{disableValidation}
|
||||||
>
|
{editAutoColumns}
|
||||||
<slot />
|
>
|
||||||
</InnerForm>
|
<slot />
|
||||||
{/key}
|
</InnerForm>
|
||||||
|
{/key}
|
||||||
|
{/if}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import { Table, Skeleton } from "@budibase/bbui"
|
import { Table } from "@budibase/bbui"
|
||||||
import SlotRenderer from "./SlotRenderer.svelte"
|
import SlotRenderer from "./SlotRenderer.svelte"
|
||||||
import { UnsortableTypes } from "../../../constants"
|
import { UnsortableTypes } from "../../../constants"
|
||||||
import { onDestroy } from "svelte"
|
import { onDestroy } from "svelte"
|
||||||
|
@ -14,7 +14,6 @@
|
||||||
export let compact
|
export let compact
|
||||||
export let onClick
|
export let onClick
|
||||||
|
|
||||||
const loading = getContext("loading")
|
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
const { styleable, getAction, ActionTypes, rowSelectionStore } =
|
const { styleable, getAction, ActionTypes, rowSelectionStore } =
|
||||||
getContext("sdk")
|
getContext("sdk")
|
||||||
|
@ -29,6 +28,7 @@
|
||||||
let selectedRows = []
|
let selectedRows = []
|
||||||
|
|
||||||
$: hasChildren = $component.children
|
$: hasChildren = $component.children
|
||||||
|
$: loading = dataProvider?.loading ?? false
|
||||||
$: data = dataProvider?.rows || []
|
$: data = dataProvider?.rows || []
|
||||||
$: fullSchema = dataProvider?.schema ?? {}
|
$: fullSchema = dataProvider?.schema ?? {}
|
||||||
$: fields = getFields(fullSchema, columns, false)
|
$: fields = getFields(fullSchema, columns, false)
|
||||||
|
@ -130,7 +130,7 @@
|
||||||
<Table
|
<Table
|
||||||
{data}
|
{data}
|
||||||
{schema}
|
{schema}
|
||||||
loading={$loading}
|
{loading}
|
||||||
{rowCount}
|
{rowCount}
|
||||||
{quiet}
|
{quiet}
|
||||||
{compact}
|
{compact}
|
||||||
|
@ -145,9 +145,6 @@
|
||||||
on:sort={onSort}
|
on:sort={onSort}
|
||||||
on:click={handleClick}
|
on:click={handleClick}
|
||||||
>
|
>
|
||||||
<div class="skeleton" slot="loadingIndicator">
|
|
||||||
<Skeleton />
|
|
||||||
</div>
|
|
||||||
<slot />
|
<slot />
|
||||||
</Table>
|
</Table>
|
||||||
{#if allowSelectRows && selectedRows.length}
|
{#if allowSelectRows && selectedRows.length}
|
||||||
|
@ -161,12 +158,6 @@
|
||||||
div {
|
div {
|
||||||
background-color: var(--spectrum-alias-background-color-secondary);
|
background-color: var(--spectrum-alias-background-color-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.skeleton {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row-count {
|
.row-count {
|
||||||
margin-top: var(--spacing-l);
|
margin-top: var(--spacing-l);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue