More fixes (#9387)
* Mark filters as nested settings to support persisting bindings post block ejection * Add support for searching on linked fields in blocks * Fix multi-select pickers closing on every click * Target spectrum root element by default when rendering popovers, and allow customisation via context for client library * Don't send up invalid HBS expressions when filtering on dates in blocks with empty date value * Move profile above theme in user dropdown
This commit is contained in:
parent
d5aebb3db4
commit
2a2466fbda
|
@ -45,7 +45,9 @@
|
||||||
getOptionLabel
|
getOptionLabel
|
||||||
)
|
)
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = e => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
dispatch("click")
|
dispatch("click")
|
||||||
if (readonly) {
|
if (readonly) {
|
||||||
return
|
return
|
||||||
|
@ -88,7 +90,6 @@
|
||||||
class:is-open={open}
|
class:is-open={open}
|
||||||
aria-haspopup="listbox"
|
aria-haspopup="listbox"
|
||||||
on:click={onClick}
|
on:click={onClick}
|
||||||
use:clickOutside={() => (open = false)}
|
|
||||||
bind:this={button}
|
bind:this={button}
|
||||||
>
|
>
|
||||||
{#if fieldIcon}
|
{#if fieldIcon}
|
||||||
|
@ -130,14 +131,17 @@
|
||||||
<Popover
|
<Popover
|
||||||
anchor={button}
|
anchor={button}
|
||||||
align="left"
|
align="left"
|
||||||
portalTarget={document.documentElement}
|
|
||||||
bind:this={popover}
|
bind:this={popover}
|
||||||
{open}
|
{open}
|
||||||
on:close={() => (open = false)}
|
on:close={() => (open = false)}
|
||||||
useAnchorWidth={!autoWidth}
|
useAnchorWidth={!autoWidth}
|
||||||
maxWidth={autoWidth ? 400 : null}
|
maxWidth={autoWidth ? 400 : null}
|
||||||
>
|
>
|
||||||
<div class="popover-content" class:auto-width={autoWidth}>
|
<div
|
||||||
|
class="popover-content"
|
||||||
|
class:auto-width={autoWidth}
|
||||||
|
use:clickOutside={() => (open = false)}
|
||||||
|
>
|
||||||
{#if autocomplete}
|
{#if autocomplete}
|
||||||
<Search
|
<Search
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
import positionDropdown from "../Actions/position_dropdown"
|
import positionDropdown from "../Actions/position_dropdown"
|
||||||
import clickOutside from "../Actions/click_outside"
|
import clickOutside from "../Actions/click_outside"
|
||||||
import { fly } from "svelte/transition"
|
import { fly } from "svelte/transition"
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import Context from "../context"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
@ -24,6 +26,7 @@
|
||||||
$: tooltipClasses = showTip
|
$: tooltipClasses = showTip
|
||||||
? `spectrum-Popover--withTip spectrum-Popover--${direction}`
|
? `spectrum-Popover--withTip spectrum-Popover--${direction}`
|
||||||
: ""
|
: ""
|
||||||
|
$: target = portalTarget || getContext(Context.PopoverRoot) || ".spectrum"
|
||||||
|
|
||||||
export const show = () => {
|
export const show = () => {
|
||||||
dispatch("open")
|
dispatch("open")
|
||||||
|
@ -61,7 +64,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if open}
|
{#if open}
|
||||||
<Portal target={portalTarget}>
|
<Portal {target}>
|
||||||
<div
|
<div
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
use:positionDropdown={{ anchor, align, maxWidth, useAnchorWidth }}
|
use:positionDropdown={{ anchor, align, maxWidth, useAnchorWidth }}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export default {
|
export default {
|
||||||
Modal: "bbui-modal",
|
Modal: "bbui-modal",
|
||||||
|
PopoverRoot: "bbui-popover-root",
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,6 @@
|
||||||
<Avatar size="M" initials={$auth.initials} url={$auth.user.pictureUrl} />
|
<Avatar size="M" initials={$auth.initials} url={$auth.user.pictureUrl} />
|
||||||
<Icon size="XL" name="ChevronDown" />
|
<Icon size="XL" name="ChevronDown" />
|
||||||
</div>
|
</div>
|
||||||
<MenuItem icon="Moon" on:click={() => themeModal.show()} dataCy="theme">
|
|
||||||
Theme
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon="UserEdit"
|
icon="UserEdit"
|
||||||
on:click={() => profileModal.show()}
|
on:click={() => profileModal.show()}
|
||||||
|
@ -36,6 +33,9 @@
|
||||||
>
|
>
|
||||||
My profile
|
My profile
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem icon="Moon" on:click={() => themeModal.show()} dataCy="theme">
|
||||||
|
Theme
|
||||||
|
</MenuItem>
|
||||||
<MenuItem icon="LockClosed" on:click={() => updatePasswordModal.show()}>
|
<MenuItem icon="LockClosed" on:click={() => updatePasswordModal.show()}>
|
||||||
Update password
|
Update password
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
|
@ -4019,7 +4019,8 @@
|
||||||
{
|
{
|
||||||
"type": "filter",
|
"type": "filter",
|
||||||
"label": "Filtering",
|
"label": "Filtering",
|
||||||
"key": "filter"
|
"key": "filter",
|
||||||
|
"nested": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "field",
|
"type": "field",
|
||||||
|
@ -4535,7 +4536,8 @@
|
||||||
{
|
{
|
||||||
"type": "filter",
|
"type": "filter",
|
||||||
"label": "Filtering",
|
"label": "Filtering",
|
||||||
"key": "filter"
|
"key": "filter",
|
||||||
|
"nested": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "searchfield",
|
"type": "searchfield",
|
||||||
|
@ -4665,7 +4667,8 @@
|
||||||
{
|
{
|
||||||
"type": "filter",
|
"type": "filter",
|
||||||
"label": "Filtering",
|
"label": "Filtering",
|
||||||
"key": "filter"
|
"key": "filter",
|
||||||
|
"nested": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "field/sortable",
|
"type": "field/sortable",
|
||||||
|
@ -4831,7 +4834,8 @@
|
||||||
{
|
{
|
||||||
"type": "filter",
|
"type": "filter",
|
||||||
"label": "Filtering",
|
"label": "Filtering",
|
||||||
"key": "filter"
|
"key": "filter",
|
||||||
|
"nested": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "field/sortable",
|
"type": "field/sortable",
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import { themeStore } from "stores"
|
import { themeStore } from "stores"
|
||||||
|
import { setContext } from "svelte"
|
||||||
|
import { Context } from "@budibase/bbui"
|
||||||
|
|
||||||
|
setContext(Context.PopoverRoot, "#theme-root")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div style={$themeStore.customThemeCss} id="theme-root">
|
<div style={$themeStore.customThemeCss} id="theme-root">
|
||||||
|
|
|
@ -36,9 +36,12 @@
|
||||||
let dataProviderId
|
let dataProviderId
|
||||||
let repeaterId
|
let repeaterId
|
||||||
let schema
|
let schema
|
||||||
|
let enrichedSearchColumns
|
||||||
|
|
||||||
$: fetchSchema(dataSource)
|
$: fetchSchema(dataSource)
|
||||||
$: enrichedSearchColumns = enrichSearchColumns(searchColumns, schema)
|
$: enrichSearchColumns(searchColumns, schema).then(
|
||||||
|
val => (enrichedSearchColumns = val)
|
||||||
|
)
|
||||||
$: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId)
|
$: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId)
|
||||||
$: cardWidth = cardHorizontal ? 420 : 300
|
$: cardWidth = cardHorizontal ? 420 : 300
|
||||||
$: fullCardURL = buildFullCardUrl(
|
$: fullCardURL = buildFullCardUrl(
|
||||||
|
|
|
@ -36,9 +36,12 @@
|
||||||
let newRowSidePanelId
|
let newRowSidePanelId
|
||||||
let schema
|
let schema
|
||||||
let primaryDisplay
|
let primaryDisplay
|
||||||
|
let enrichedSearchColumns
|
||||||
|
|
||||||
$: fetchSchema(dataSource)
|
$: fetchSchema(dataSource)
|
||||||
$: enrichedSearchColumns = enrichSearchColumns(searchColumns, schema)
|
$: enrichSearchColumns(searchColumns, schema).then(
|
||||||
|
val => (enrichedSearchColumns = val)
|
||||||
|
)
|
||||||
$: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId)
|
$: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId)
|
||||||
$: editTitle = getEditTitle(detailsFormBlockId, primaryDisplay)
|
$: editTitle = getEditTitle(detailsFormBlockId, primaryDisplay)
|
||||||
$: normalFields = getNormalFields(schema)
|
$: normalFields = getNormalFields(schema)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { makePropSafe as safe } from "@budibase/string-templates"
|
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||||
|
import { API } from "../api/index.js"
|
||||||
|
|
||||||
// Map of data types to component types for search fields inside blocks
|
// Map of data types to component types for search fields inside blocks
|
||||||
const schemaComponentMap = {
|
const schemaComponentMap = {
|
||||||
|
@ -15,10 +16,28 @@ const schemaComponentMap = {
|
||||||
* @param searchColumns the search columns to use
|
* @param searchColumns the search columns to use
|
||||||
* @param schema the datasource schema
|
* @param schema the datasource schema
|
||||||
*/
|
*/
|
||||||
export const enrichSearchColumns = (searchColumns, schema) => {
|
export const enrichSearchColumns = async (searchColumns, schema) => {
|
||||||
|
if (!searchColumns?.length || !schema) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
let enrichedColumns = []
|
let enrichedColumns = []
|
||||||
searchColumns?.forEach(column => {
|
for (let column of searchColumns) {
|
||||||
const schemaType = schema?.[column]?.type
|
let schemaType = schema[column]?.type
|
||||||
|
|
||||||
|
// Check if this is a field in another related table. The only way we can
|
||||||
|
// check this is checking for a "." inside the column, then checking if we
|
||||||
|
// have a link field named the same as that field prefix.
|
||||||
|
if (column.includes(".")) {
|
||||||
|
const split = column.split(".")
|
||||||
|
const sourceField = split[0]
|
||||||
|
const linkField = split.slice(1).join(".")
|
||||||
|
const linkSchema = schema[sourceField]
|
||||||
|
if (linkSchema?.type === "link") {
|
||||||
|
const linkedDef = await API.fetchTableDefinition(linkSchema.tableId)
|
||||||
|
schemaType = linkedDef?.schema?.[linkField]?.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const componentType = schemaComponentMap[schemaType]
|
const componentType = schemaComponentMap[schemaType]
|
||||||
if (componentType) {
|
if (componentType) {
|
||||||
enrichedColumns.push({
|
enrichedColumns.push({
|
||||||
|
@ -27,7 +46,7 @@ export const enrichSearchColumns = (searchColumns, schema) => {
|
||||||
type: schemaType,
|
type: schemaType,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
return enrichedColumns.slice(0, 5)
|
return enrichedColumns.slice(0, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,12 +76,14 @@ export const enrichFilter = (filter, columns, formId) => {
|
||||||
value: `{{ ${binding} }}`,
|
value: `{{ ${binding} }}`,
|
||||||
})
|
})
|
||||||
const format = "YYYY-MM-DDTHH:mm:ss.SSSZ"
|
const format = "YYYY-MM-DDTHH:mm:ss.SSSZ"
|
||||||
|
let hbs = `{{ date (add (date ${binding} "x") 86399999) "${format}" }}`
|
||||||
|
hbs = `{{#if ${binding} }}${hbs}{{/if}}`
|
||||||
enrichedFilter.push({
|
enrichedFilter.push({
|
||||||
field: column.name,
|
field: column.name,
|
||||||
type: column.type,
|
type: column.type,
|
||||||
operator: "rangeHigh",
|
operator: "rangeHigh",
|
||||||
valueType: "Binding",
|
valueType: "Binding",
|
||||||
value: `{{ date (add (date ${binding} "x") 86399999) "${format}" }}`,
|
value: hbs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue