Update relationship cells to use popovers

This commit is contained in:
Andrew Kingston 2024-04-24 20:26:58 +01:00
parent 377cd97f4b
commit 23bd635a8b
6 changed files with 70 additions and 59 deletions

View File

@ -93,7 +93,14 @@
</div>
{#if isOpen}
<GridPopover open={isOpen} {anchor} {gridID} {invertX} on:close={close}>
<GridPopover
open={isOpen}
{anchor}
{gridID}
{invertX}
maxHeight={null}
on:close={close}
>
<div class="dropzone">
<Dropzone
{value}

View File

@ -112,7 +112,7 @@
</div>
{#if isOpen}
<GridPopover open={isOpen} {anchor} {invertX} {gridID} on:close={close}>
<GridPopover {anchor} {invertX} maxHeight={null} on:close={close}>
<CoreDatePickerPopoverContents
value={parsedValue}
useKeyboardShortcuts={false}

View File

@ -121,8 +121,8 @@
</div>
{#if isOpen}
<GridPopover open={isOpen} {anchor} {gridID} {invertX} on:close={close}>
<div class="options" on:wheel={e => e.stopPropagation()}>
<GridPopover {anchor} {invertX} on:close={close}>
<div class="options">
{#each options as option, idx}
{@const color = optionColors[option] || getOptionColor(option)}
<!-- svelte-ignore a11y-no-static-element-interactions -->
@ -219,10 +219,6 @@
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
max-height: var(--max-cell-render-overflow);
overflow-y: auto;
min-width: 200px;
max-width: 400px;
}
.option {
flex: 0 0 var(--default-row-height);

View File

@ -1,8 +1,9 @@
<script>
import { getColor } from "../lib/utils"
import { onMount, getContext } from "svelte"
import { Icon, Input, ProgressCircle, clickOutside } from "@budibase/bbui"
import { Icon, Input, ProgressCircle } from "@budibase/bbui"
import { debounce } from "../../../utils/utils"
import GridPopover from "../overlays/GridPopover.svelte"
const { API, dispatch, cache } = getContext("grid")
@ -17,6 +18,7 @@
export let contentLines = 1
export let searchFunction = API.searchTable
export let primaryDisplay
export let gridID
const color = getColor(0)
@ -27,8 +29,8 @@
let candidateIndex
let lastSearchId
let searching = false
let valuesHeight = 0
let container
let anchor
$: oneRowOnly = schema?.relationshipType === "one-to-many"
$: editable = focused && !readonly
@ -125,7 +127,6 @@
const open = async () => {
isOpen = true
valuesHeight = container.getBoundingClientRect().height
// Find the primary display for the related table
if (!primaryDisplay) {
@ -240,6 +241,7 @@
class:focused
class:invertY
style="--color:{color};"
bind:this={anchor}
>
<div class="container" bind:this={container}>
<div
@ -250,11 +252,7 @@
{#each value || [] as relationship}
{#if relationship[primaryDisplay] || relationship.primaryDisplay}
<div class="badge">
<span
on:click={editable
? () => showRelationship(relationship._id)
: null}
>
<span>
{readable(
relationship[primaryDisplay] || relationship.primaryDisplay
)}
@ -282,16 +280,11 @@
</div>
{/if}
</div>
</div>
{#if isOpen}
<div
class="dropdown"
class:invertX
class:invertY
on:wheel|stopPropagation
use:clickOutside={close}
style="--values-height:{valuesHeight}px;"
>
{#if isOpen}
<GridPopover open={isOpen} {anchor} {gridID} {invertX} on:close={close}>
<div class="dropdown" on:wheel|stopPropagation>
<div class="search">
<Input
autofocus
@ -327,8 +320,8 @@
</div>
{/if}
</div>
{/if}
</div>
</GridPopover>
{/if}
<style>
.wrapper {
@ -426,10 +419,6 @@
white-space: nowrap;
text-overflow: ellipsis;
}
.editable .values .badge span:hover {
cursor: pointer;
text-decoration: underline;
}
.add {
background: var(--spectrum-global-color-gray-200);
@ -446,30 +435,9 @@
}
.dropdown {
position: absolute;
top: 100%;
left: 0;
width: 100%;
max-height: calc(
var(--max-cell-render-overflow) + var(--row-height) - var(--values-height)
);
background: var(--grid-background-alt);
border: var(--cell-border);
box-shadow: 0 0 20px -4px rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column;
align-items: stretch;
padding: 0 0 8px 0;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
.dropdown.invertY {
transform: translateY(-100%);
top: -1px;
}
.dropdown.invertX {
left: auto;
right: 0;
}
.searching {
@ -497,7 +465,8 @@
cursor: pointer;
}
.result .badge {
max-width: calc(100% - 30px);
flex: 1 1 auto;
overflow: hidden;
}
.search {
@ -505,7 +474,6 @@
display: flex;
align-items: center;
margin: 4px var(--cell-padding);
width: calc(100% - 2 * var(--cell-padding));
}
.search :global(.spectrum-Textfield) {
min-width: 0;

View File

@ -11,4 +11,9 @@ export const NewRowID = "new"
export const BlankRowID = "blank"
export const RowPageSize = 100
export const FocusedCellMinOffset = 48
// Popovers
export const PopoverMinWidth = 200
export const PopoverMaxWidth = 400
export const PopoverMaxHeight = 236
export const MaxCellRenderOverflow = 222

View File

@ -1,23 +1,51 @@
<script>
import { Popover, clickOutside } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
import { createEventDispatcher, getContext } from "svelte"
import {
PopoverMinWidth,
PopoverMaxWidth,
PopoverMaxHeight,
} from "../lib/constants"
export let open
export let anchor
export let invertX
export let gridID
export let minWidth = PopoverMinWidth
export let maxWidth = PopoverMaxWidth
export let maxHeight = PopoverMaxHeight
const { gridID } = getContext("grid")
const dispatch = createEventDispatcher()
$: style = buildStyles(minWidth, maxWidth, maxHeight)
const buildStyles = (minWidth, maxWidth, maxHeight) => {
let style = ""
if (minWidth != null) {
style += `min-width: ${minWidth}px;`
}
if (maxWidth != null) {
style += `max-width: ${maxWidth}px;`
}
if (maxHeight != null) {
style += `max-height: ${maxHeight}px;`
}
return style
}
</script>
<Popover
bind:open
open
{anchor}
align={invertX ? "right" : "left"}
portalTarget="#{gridID} .grid-popover-container"
offset={1}
>
<div use:clickOutside={() => dispatch("close")}>
<div
class="grid-popover-contents"
{style}
use:clickOutside={() => dispatch("close")}
on:wheel={e => e.stopPropagation()}
>
<slot />
</div>
</Popover>
@ -26,5 +54,12 @@
:global(.grid-popover-container .spectrum-Popover) {
background: var(--grid-background-alt);
border: var(--cell-border);
min-width: none;
max-width: none;
overflow: hidden;
}
.grid-popover-contents {
overflow-y: auto;
overflow-x: hidden;
}
</style>