Merge branch 'master' into feature/signature-field-and-component
This commit is contained in:
commit
f20ed14e61
|
@ -1,40 +1,28 @@
|
|||
<script>
|
||||
import { getContext, onMount, createEventDispatcher } from "svelte"
|
||||
import { getContext, onDestroy } from "svelte"
|
||||
import Portal from "svelte-portal"
|
||||
|
||||
export let title
|
||||
export let icon = ""
|
||||
export let id
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let selected = getContext("tab")
|
||||
let tab_internal
|
||||
let tabInfo
|
||||
let observer
|
||||
let ref
|
||||
|
||||
const setTabInfo = () => {
|
||||
// If the tabs are being rendered inside a component which uses
|
||||
// a svelte transition to enter, then this initial getBoundingClientRect
|
||||
// will return an incorrect position.
|
||||
// We just need to get this off the main thread to fix this, by using
|
||||
// a 0ms timeout.
|
||||
setTimeout(() => {
|
||||
tabInfo = tab_internal?.getBoundingClientRect()
|
||||
if (tabInfo && $selected.title === title) {
|
||||
$selected.info = tabInfo
|
||||
}
|
||||
}, 0)
|
||||
$: isSelected = $selected.title === title
|
||||
$: {
|
||||
if (isSelected && ref) {
|
||||
observe()
|
||||
} else {
|
||||
stopObserving()
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
setTabInfo()
|
||||
})
|
||||
|
||||
//Ensure that the underline is in the correct location
|
||||
$: {
|
||||
if ($selected.title === title && tab_internal) {
|
||||
if ($selected.info?.left !== tab_internal.getBoundingClientRect().left) {
|
||||
setTabInfo()
|
||||
}
|
||||
const setTabInfo = () => {
|
||||
const tabInfo = ref?.getBoundingClientRect()
|
||||
if (tabInfo) {
|
||||
$selected.info = tabInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,10 +30,25 @@
|
|||
$selected = {
|
||||
...$selected,
|
||||
title,
|
||||
info: tab_internal.getBoundingClientRect(),
|
||||
info: ref.getBoundingClientRect(),
|
||||
}
|
||||
dispatch("click")
|
||||
}
|
||||
|
||||
const observe = () => {
|
||||
if (!observer) {
|
||||
observer = new ResizeObserver(setTabInfo)
|
||||
observer.observe(ref)
|
||||
}
|
||||
}
|
||||
|
||||
const stopObserving = () => {
|
||||
if (observer) {
|
||||
observer.unobserve(ref)
|
||||
observer = null
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(stopObserving)
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
|
@ -53,11 +56,12 @@
|
|||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<div
|
||||
{id}
|
||||
bind:this={tab_internal}
|
||||
bind:this={ref}
|
||||
on:click={onClick}
|
||||
class:is-selected={$selected.title === title}
|
||||
on:click
|
||||
class="spectrum-Tabs-item"
|
||||
class:emphasized={$selected.title === title && $selected.emphasized}
|
||||
class:is-selected={isSelected}
|
||||
class:emphasized={isSelected && $selected.emphasized}
|
||||
tabindex="0"
|
||||
>
|
||||
{#if icon}
|
||||
|
@ -72,7 +76,8 @@
|
|||
{/if}
|
||||
<span class="spectrum-Tabs-itemLabel">{title}</span>
|
||||
</div>
|
||||
{#if $selected.title === title}
|
||||
|
||||
{#if isSelected}
|
||||
<Portal target=".spectrum-Tabs-content-{$selected.id}">
|
||||
<slot />
|
||||
</Portal>
|
||||
|
|
|
@ -105,10 +105,6 @@
|
|||
}
|
||||
|
||||
onMount(async () => {
|
||||
document.fonts.onloadingdone = e => {
|
||||
builderStore.loadFonts(e.fontfaces)
|
||||
}
|
||||
|
||||
if (!hasSynced && application) {
|
||||
try {
|
||||
await API.syncApp(application)
|
||||
|
@ -149,19 +145,17 @@
|
|||
/>
|
||||
</span>
|
||||
<Tabs {selected} size="M">
|
||||
{#key $builderStore?.fonts}
|
||||
{#each $layout.children as { path, title }}
|
||||
<TourWrap stepKeys={[`builder-${title}-section`]}>
|
||||
<Tab
|
||||
quiet
|
||||
selected={$isActive(path)}
|
||||
on:click={topItemNavigate(path)}
|
||||
title={capitalise(title)}
|
||||
id={`builder-${title}-tab`}
|
||||
/>
|
||||
</TourWrap>
|
||||
{/each}
|
||||
{/key}
|
||||
{#each $layout.children as { path, title }}
|
||||
<TourWrap stepKeys={[`builder-${title}-section`]}>
|
||||
<Tab
|
||||
quiet
|
||||
selected={$isActive(path)}
|
||||
on:click={topItemNavigate(path)}
|
||||
title={capitalise(title)}
|
||||
id={`builder-${title}-tab`}
|
||||
/>
|
||||
</TourWrap>
|
||||
{/each}
|
||||
</Tabs>
|
||||
</div>
|
||||
<div class="topcenternav">
|
||||
|
|
|
@ -14,7 +14,6 @@ export const INITIAL_BUILDER_STATE = {
|
|||
tourKey: null,
|
||||
tourStepKey: null,
|
||||
hoveredComponentId: null,
|
||||
fonts: null,
|
||||
}
|
||||
|
||||
export class BuilderStore extends BudiStore {
|
||||
|
@ -37,16 +36,6 @@ export class BuilderStore extends BudiStore {
|
|||
this.websocket
|
||||
}
|
||||
|
||||
loadFonts(fontFaces) {
|
||||
const ff = fontFaces.map(
|
||||
fontFace => `${fontFace.family}-${fontFace.weight}`
|
||||
)
|
||||
this.update(state => ({
|
||||
...state,
|
||||
fonts: [...(state.fonts || []), ...ff],
|
||||
}))
|
||||
}
|
||||
|
||||
init(app) {
|
||||
if (!app?.appId) {
|
||||
console.error("BuilderStore: No appId supplied for websocket")
|
||||
|
|
|
@ -14,7 +14,7 @@ import { makeExternalQuery } from "../../../integrations/base/query"
|
|||
import { Format } from "../../../api/controllers/view/exporters"
|
||||
import sdk from "../.."
|
||||
import { isRelationshipColumn } from "../../../db/utils"
|
||||
import { SqlClient, isSQL } from "../../../integrations/utils"
|
||||
import { isSQL, SqlClient } from "../../../integrations/utils"
|
||||
|
||||
const SQL_CLIENT_SOURCE_MAP: Record<SourceName, SqlClient | undefined> = {
|
||||
[SourceName.POSTGRES]: SqlClient.POSTGRES,
|
||||
|
@ -144,6 +144,10 @@ export async function validate({
|
|||
throw new Error("Unable to fetch table for validation")
|
||||
}
|
||||
const errors: Record<string, any> = {}
|
||||
const disallowArrayTypes = [
|
||||
FieldType.ATTACHMENT_SINGLE,
|
||||
FieldType.BB_REFERENCE_SINGLE,
|
||||
]
|
||||
for (let fieldName of Object.keys(fetchedTable.schema)) {
|
||||
const column = fetchedTable.schema[fieldName]
|
||||
const constraints = cloneDeep(column.constraints)
|
||||
|
@ -160,6 +164,10 @@ export async function validate({
|
|||
if (type === FieldType.OPTIONS && constraints?.inclusion) {
|
||||
constraints.inclusion.push(null as any, "")
|
||||
}
|
||||
|
||||
if (disallowArrayTypes.includes(type) && Array.isArray(row[fieldName])) {
|
||||
errors[fieldName] = `Cannot accept arrays`
|
||||
}
|
||||
let res
|
||||
|
||||
// Validate.js doesn't seem to handle array
|
||||
|
|
Loading…
Reference in New Issue