Merge pull request #5010 from Budibase/cheeks-fixes
Miscellaneous fixes
This commit is contained in:
commit
fead539800
|
@ -68,6 +68,7 @@
|
||||||
customTheme: $store.customTheme,
|
customTheme: $store.customTheme,
|
||||||
previewDevice: $store.previewDevice,
|
previewDevice: $store.previewDevice,
|
||||||
messagePassing: $store.clientFeatures.messagePassing,
|
messagePassing: $store.clientFeatures.messagePassing,
|
||||||
|
isBudibaseEvent: true
|
||||||
}
|
}
|
||||||
$: json = JSON.stringify(previewData)
|
$: json = JSON.stringify(previewData)
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ export default `
|
||||||
console.error("Client received invalid JSON")
|
console.error("Client received invalid JSON")
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
if (!parsed) {
|
if (!parsed || !parsed.isBudibaseEvent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,13 @@
|
||||||
div :global(.apexcharts-datalabel) {
|
div :global(.apexcharts-datalabel) {
|
||||||
fill: var(--spectrum-global-color-gray-800);
|
fill: var(--spectrum-global-color-gray-800);
|
||||||
}
|
}
|
||||||
|
div :global(.apexcharts-tooltip) {
|
||||||
|
background-color: var(--spectrum-global-color-gray-200) !important;
|
||||||
|
border-color: var(--spectrum-global-color-gray-300) !important;
|
||||||
|
box-shadow: 2px 2px 6px -4px rgba(0, 0, 0, 0.1) !important;
|
||||||
|
}
|
||||||
|
div :global(.apexcharts-tooltip-title) {
|
||||||
|
background-color: var(--spectrum-global-color-gray-100) !important;
|
||||||
|
border-color: var(--spectrum-global-color-gray-300) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -18,16 +18,53 @@
|
||||||
export let palette
|
export let palette
|
||||||
export let horizontal
|
export let horizontal
|
||||||
|
|
||||||
$: options = setUpChart(dataProvider)
|
$: options = setUpChart(
|
||||||
|
title,
|
||||||
|
dataProvider,
|
||||||
|
labelColumn,
|
||||||
|
valueColumns,
|
||||||
|
xAxisLabel,
|
||||||
|
yAxisLabel,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
dataLabels,
|
||||||
|
animate,
|
||||||
|
legend,
|
||||||
|
stacked,
|
||||||
|
yAxisUnits,
|
||||||
|
palette,
|
||||||
|
horizontal
|
||||||
|
)
|
||||||
|
|
||||||
const setUpChart = provider => {
|
const setUpChart = (
|
||||||
|
title,
|
||||||
|
dataProvider,
|
||||||
|
labelColumn,
|
||||||
|
valueColumns,
|
||||||
|
xAxisLabel,
|
||||||
|
yAxisLabel,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
dataLabels,
|
||||||
|
animate,
|
||||||
|
legend,
|
||||||
|
stacked,
|
||||||
|
yAxisUnits,
|
||||||
|
palette,
|
||||||
|
horizontal
|
||||||
|
) => {
|
||||||
|
console.log("new chart")
|
||||||
const allCols = [labelColumn, ...(valueColumns || [null])]
|
const allCols = [labelColumn, ...(valueColumns || [null])]
|
||||||
if (!provider || !provider.rows?.length || allCols.find(x => x == null)) {
|
if (
|
||||||
|
!dataProvider ||
|
||||||
|
!dataProvider.rows?.length ||
|
||||||
|
allCols.find(x => x == null)
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch data
|
// Fetch data
|
||||||
const { schema, rows } = provider
|
const { schema, rows } = dataProvider
|
||||||
const reducer = row => (valid, column) => valid && row[column] != null
|
const reducer = row => (valid, column) => valid && row[column] != null
|
||||||
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
||||||
const data = rows.filter(row => hasAllColumns(row)).slice(0, 100)
|
const data = rows.filter(row => hasAllColumns(row)).slice(0, 100)
|
||||||
|
|
|
@ -16,17 +16,48 @@
|
||||||
export let animate
|
export let animate
|
||||||
export let yAxisUnits
|
export let yAxisUnits
|
||||||
|
|
||||||
$: options = setUpChart(dataProvider)
|
$: options = setUpChart(
|
||||||
|
title,
|
||||||
|
dataProvider,
|
||||||
|
dateColumn,
|
||||||
|
openColumn,
|
||||||
|
highColumn,
|
||||||
|
lowColumn,
|
||||||
|
closeColumn,
|
||||||
|
xAxisLabel,
|
||||||
|
yAxisLabel,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
animate,
|
||||||
|
yAxisUnits
|
||||||
|
)
|
||||||
|
|
||||||
// Fetch data on mount
|
const setUpChart = (
|
||||||
const setUpChart = provider => {
|
title,
|
||||||
|
dataProvider,
|
||||||
|
dateColumn,
|
||||||
|
openColumn,
|
||||||
|
highColumn,
|
||||||
|
lowColumn,
|
||||||
|
closeColumn,
|
||||||
|
xAxisLabel,
|
||||||
|
yAxisLabel,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
animate,
|
||||||
|
yAxisUnits
|
||||||
|
) => {
|
||||||
const allCols = [dateColumn, openColumn, highColumn, lowColumn, closeColumn]
|
const allCols = [dateColumn, openColumn, highColumn, lowColumn, closeColumn]
|
||||||
if (!provider || !provider.rows?.length || allCols.find(x => x == null)) {
|
if (
|
||||||
|
!dataProvider ||
|
||||||
|
!dataProvider.rows?.length ||
|
||||||
|
allCols.find(x => x == null)
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch data
|
// Fetch data
|
||||||
const { schema, rows } = provider
|
const { schema, rows } = dataProvider
|
||||||
const reducer = row => (valid, column) => valid && row[column] != null
|
const reducer = row => (valid, column) => valid && row[column] != null
|
||||||
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
||||||
const data = rows.filter(row => hasAllColumns(row))
|
const data = rows.filter(row => hasAllColumns(row))
|
||||||
|
|
|
@ -23,17 +23,56 @@
|
||||||
export let stacked
|
export let stacked
|
||||||
export let gradient
|
export let gradient
|
||||||
|
|
||||||
$: options = setUpChart(dataProvider)
|
$: options = setUpChart(
|
||||||
|
title,
|
||||||
|
dataProvider,
|
||||||
|
labelColumn,
|
||||||
|
valueColumns,
|
||||||
|
xAxisLabel,
|
||||||
|
yAxisLabel,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
animate,
|
||||||
|
dataLabels,
|
||||||
|
curve,
|
||||||
|
legend,
|
||||||
|
yAxisUnits,
|
||||||
|
palette,
|
||||||
|
area,
|
||||||
|
stacked,
|
||||||
|
gradient
|
||||||
|
)
|
||||||
|
|
||||||
// Fetch data on mount
|
const setUpChart = (
|
||||||
const setUpChart = provider => {
|
title,
|
||||||
|
dataProvider,
|
||||||
|
labelColumn,
|
||||||
|
valueColumns,
|
||||||
|
xAxisLabel,
|
||||||
|
yAxisLabel,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
animate,
|
||||||
|
dataLabels,
|
||||||
|
curve,
|
||||||
|
legend,
|
||||||
|
yAxisUnits,
|
||||||
|
palette,
|
||||||
|
area,
|
||||||
|
stacked,
|
||||||
|
gradient
|
||||||
|
) => {
|
||||||
const allCols = [labelColumn, ...(valueColumns || [null])]
|
const allCols = [labelColumn, ...(valueColumns || [null])]
|
||||||
if (!provider || !provider.rows?.length || allCols.find(x => x == null)) {
|
if (
|
||||||
|
!dataProvider ||
|
||||||
|
!dataProvider.rows?.length ||
|
||||||
|
allCols.find(x => x == null)
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch, filter and sort data
|
// Fetch, filter and sort data
|
||||||
const { schema, rows } = provider
|
const { schema, rows } = dataProvider
|
||||||
const reducer = row => (valid, column) => valid && row[column] != null
|
const reducer = row => (valid, column) => valid && row[column] != null
|
||||||
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
const hasAllColumns = row => allCols.reduce(reducer(row), true)
|
||||||
const data = rows.filter(row => hasAllColumns(row))
|
const data = rows.filter(row => hasAllColumns(row))
|
||||||
|
|
|
@ -14,16 +14,44 @@
|
||||||
export let donut
|
export let donut
|
||||||
export let palette
|
export let palette
|
||||||
|
|
||||||
$: options = setUpChart(dataProvider)
|
$: options = setUpChart(
|
||||||
|
title,
|
||||||
|
dataProvider,
|
||||||
|
labelColumn,
|
||||||
|
valueColumn,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
dataLabels,
|
||||||
|
animate,
|
||||||
|
legend,
|
||||||
|
donut,
|
||||||
|
palette
|
||||||
|
)
|
||||||
|
|
||||||
// Fetch data on mount
|
const setUpChart = (
|
||||||
const setUpChart = provider => {
|
title,
|
||||||
if (!provider || !provider.rows?.length || !labelColumn || !valueColumn) {
|
dataProvider,
|
||||||
|
labelColumn,
|
||||||
|
valueColumn,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
dataLabels,
|
||||||
|
animate,
|
||||||
|
legend,
|
||||||
|
donut,
|
||||||
|
palette
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
!dataProvider ||
|
||||||
|
!dataProvider.rows?.length ||
|
||||||
|
!labelColumn ||
|
||||||
|
!valueColumn
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch, filter and sort data
|
// Fetch, filter and sort data
|
||||||
const { schema, rows } = provider
|
const { schema, rows } = dataProvider
|
||||||
const data = rows
|
const data = rows
|
||||||
.filter(row => row[labelColumn] != null && row[valueColumn] != null)
|
.filter(row => row[labelColumn] != null && row[valueColumn] != null)
|
||||||
.slice(0, 100)
|
.slice(0, 100)
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
Button,
|
Button,
|
||||||
Combobox,
|
Combobox,
|
||||||
DatePicker,
|
DatePicker,
|
||||||
DrawerContent,
|
|
||||||
Icon,
|
Icon,
|
||||||
Input,
|
Input,
|
||||||
Layout,
|
Layout,
|
||||||
|
@ -12,10 +11,12 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { generate } from "shortid"
|
import { generate } from "shortid"
|
||||||
import { LuceneUtils, Constants } from "@budibase/frontend-core"
|
import { LuceneUtils, Constants } from "@budibase/frontend-core"
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
export let schemaFields
|
export let schemaFields
|
||||||
export let filters = []
|
export let filters = []
|
||||||
|
|
||||||
|
const context = getContext("context")
|
||||||
const BannedTypes = ["link", "attachment", "json"]
|
const BannedTypes = ["link", "attachment", "json"]
|
||||||
|
|
||||||
$: fieldOptions = (schemaFields ?? [])
|
$: fieldOptions = (schemaFields ?? [])
|
||||||
|
@ -89,55 +90,55 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DrawerContent>
|
<div class="container" class:mobile={$context.device.mobile}>
|
||||||
<div class="container">
|
<Layout noPadding>
|
||||||
<Layout noPadding>
|
<Body size="S">
|
||||||
<Body size="S">
|
{#if !filters?.length}
|
||||||
{#if !filters?.length}
|
Add your first filter expression.
|
||||||
Add your first filter expression.
|
{:else}
|
||||||
{:else}
|
Results are filtered to only those which match all of the following
|
||||||
Results are filtered to only those which match all of the following
|
constraints.
|
||||||
constraints.
|
{/if}
|
||||||
{/if}
|
</Body>
|
||||||
</Body>
|
{#if filters?.length}
|
||||||
{#if filters?.length}
|
<div class="fields">
|
||||||
<div class="fields">
|
{#each filters as filter, idx}
|
||||||
{#each filters as filter, idx}
|
<Select
|
||||||
<Select
|
bind:value={filter.field}
|
||||||
bind:value={filter.field}
|
options={fieldOptions}
|
||||||
options={fieldOptions}
|
on:change={e => onFieldChange(filter, e.detail)}
|
||||||
on:change={e => onFieldChange(filter, e.detail)}
|
placeholder="Column"
|
||||||
placeholder="Column"
|
/>
|
||||||
|
<Select
|
||||||
|
disabled={!filter.field}
|
||||||
|
options={LuceneUtils.getValidOperatorsForType(filter.type)}
|
||||||
|
bind:value={filter.operator}
|
||||||
|
on:change={e => onOperatorChange(filter, e.detail)}
|
||||||
|
placeholder={null}
|
||||||
|
/>
|
||||||
|
{#if ["string", "longform", "number", "formula"].includes(filter.type)}
|
||||||
|
<Input disabled={filter.noValue} bind:value={filter.value} />
|
||||||
|
{:else if ["options", "array"].includes(filter.type)}
|
||||||
|
<Combobox
|
||||||
|
disabled={filter.noValue}
|
||||||
|
options={getFieldOptions(filter.field)}
|
||||||
|
bind:value={filter.value}
|
||||||
/>
|
/>
|
||||||
<Select
|
{:else if filter.type === "boolean"}
|
||||||
disabled={!filter.field}
|
<Combobox
|
||||||
options={LuceneUtils.getValidOperatorsForType(filter.type)}
|
disabled={filter.noValue}
|
||||||
bind:value={filter.operator}
|
options={[
|
||||||
on:change={e => onOperatorChange(filter, e.detail)}
|
{ label: "True", value: "true" },
|
||||||
placeholder={null}
|
{ label: "False", value: "false" },
|
||||||
|
]}
|
||||||
|
bind:value={filter.value}
|
||||||
/>
|
/>
|
||||||
{#if ["string", "longform", "number", "formula"].includes(filter.type)}
|
{:else if filter.type === "datetime"}
|
||||||
<Input disabled={filter.noValue} bind:value={filter.value} />
|
<DatePicker disabled={filter.noValue} bind:value={filter.value} />
|
||||||
{:else if ["options", "array"].includes(filter.type)}
|
{:else}
|
||||||
<Combobox
|
<Input disabled />
|
||||||
disabled={filter.noValue}
|
{/if}
|
||||||
options={getFieldOptions(filter.field)}
|
<div class="controls">
|
||||||
bind:value={filter.value}
|
|
||||||
/>
|
|
||||||
{:else if filter.type === "boolean"}
|
|
||||||
<Combobox
|
|
||||||
disabled={filter.noValue}
|
|
||||||
options={[
|
|
||||||
{ label: "True", value: "true" },
|
|
||||||
{ label: "False", value: "false" },
|
|
||||||
]}
|
|
||||||
bind:value={filter.value}
|
|
||||||
/>
|
|
||||||
{:else if filter.type === "datetime"}
|
|
||||||
<DatePicker disabled={filter.noValue} bind:value={filter.value} />
|
|
||||||
{:else}
|
|
||||||
<Input disabled />
|
|
||||||
{/if}
|
|
||||||
<Icon
|
<Icon
|
||||||
name="Duplicate"
|
name="Duplicate"
|
||||||
hoverable
|
hoverable
|
||||||
|
@ -150,17 +151,17 @@
|
||||||
size="S"
|
size="S"
|
||||||
on:click={() => removeFilter(filter.id)}
|
on:click={() => removeFilter(filter.id)}
|
||||||
/>
|
/>
|
||||||
{/each}
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
{/if}
|
|
||||||
<div>
|
|
||||||
<Button icon="AddCircle" size="M" secondary on:click={addFilter}>
|
|
||||||
Add filter
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
{/if}
|
||||||
</div>
|
<div>
|
||||||
</DrawerContent>
|
<Button icon="AddCircle" size="M" secondary on:click={addFilter}>
|
||||||
|
Add filter
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.container {
|
.container {
|
||||||
|
@ -175,4 +176,19 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
grid-template-columns: 1fr 120px 1fr auto auto;
|
grid-template-columns: 1fr 120px 1fr auto auto;
|
||||||
}
|
}
|
||||||
|
.controls {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.mobile .fields {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.container.mobile .controls {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--spacing-s) 0;
|
||||||
|
gap: var(--spacing-s);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -157,13 +157,9 @@
|
||||||
const { fieldState } = get(existingField)
|
const { fieldState } = get(existingField)
|
||||||
fieldId = fieldState.fieldId
|
fieldId = fieldState.fieldId
|
||||||
|
|
||||||
// Use new default value if default value changed,
|
// Determine the initial value for this field, reusing the current
|
||||||
// otherwise use the current value if possible
|
// value if one exists
|
||||||
if (defaultValue !== fieldState.defaultValue) {
|
initialValue = fieldState.value ?? initialValue
|
||||||
initialValue = defaultValue
|
|
||||||
} else {
|
|
||||||
initialValue = fieldState.value ?? initialValue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this field has already been registered and we previously had an
|
// If this field has already been registered and we previously had an
|
||||||
// error set, then re-run the validator to see if we can unset it
|
// error set, then re-run the validator to see if we can unset it
|
||||||
|
|
|
@ -6,12 +6,26 @@ const createAuthStore = () => {
|
||||||
|
|
||||||
// Fetches the user object if someone is logged in and has reloaded the page
|
// Fetches the user object if someone is logged in and has reloaded the page
|
||||||
const fetchUser = async () => {
|
const fetchUser = async () => {
|
||||||
|
let globalSelf = null
|
||||||
|
let appSelf = null
|
||||||
|
|
||||||
|
// First try and get the global user, to see if we are logged in at all
|
||||||
try {
|
try {
|
||||||
const user = await API.fetchSelf()
|
globalSelf = await API.fetchBuilderSelf()
|
||||||
store.set(user)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
store.set(null)
|
store.set(null)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Then try and get the user for this app to provide via context
|
||||||
|
try {
|
||||||
|
appSelf = await API.fetchSelf()
|
||||||
|
} catch (error) {
|
||||||
|
// Swallow
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the app self if present, otherwise fallback to the global self
|
||||||
|
store.set(appSelf || globalSelf || null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const logOut = async () => {
|
const logOut = async () => {
|
||||||
|
|
Loading…
Reference in New Issue