Merge pull request #10491 from Budibase/more-grid-tweaks

Grid improvements and fixes
This commit is contained in:
Andrew Kingston 2023-05-05 11:38:24 +01:00 committed by GitHub
commit 687d3a9267
17 changed files with 143 additions and 87 deletions

View File

@ -1,4 +1,8 @@
const ignoredClasses = [".flatpickr-calendar", ".spectrum-Popover"]
const ignoredClasses = [
".flatpickr-calendar",
".spectrum-Popover",
".download-js-link",
]
let clickHandlers = []
/**
@ -22,8 +26,8 @@ const handleClick = event => {
}
// Ignore clicks for modals, unless the handler is registered from a modal
const sourceInModal = handler.anchor.closest(".spectrum-Modal") != null
const clickInModal = event.target.closest(".spectrum-Modal") != null
const sourceInModal = handler.anchor.closest(".spectrum-Underlay") != null
const clickInModal = event.target.closest(".spectrum-Underlay") != null
if (clickInModal && !sourceInModal) {
return
}

View File

@ -39,7 +39,7 @@
{#if datasource}
<div>
<ActionButton icon="DataCorrelated" primary quiet on:click={modal.show}>
Define existing relationship
Define relationship
</ActionButton>
</div>
<Modal bind:this={modal}>

View File

@ -9,13 +9,21 @@
$: selectedRowArray = Object.keys($selectedRows).map(id => ({ _id: id }))
</script>
<ExportButton
{disabled}
view={$tableId}
filters={$filter}
sorting={{
sortColumn: $sort.column,
sortOrder: $sort.order,
}}
selectedRows={selectedRowArray}
/>
<span data-ignore-click-outside="true">
<ExportButton
{disabled}
view={$tableId}
filters={$filter}
sorting={{
sortColumn: $sort.column,
sortOrder: $sort.order,
}}
selectedRows={selectedRowArray}
/>
</span>
<style>
span {
display: contents;
}
</style>

View File

@ -2,19 +2,19 @@
import TableFilterButton from "../TableFilterButton.svelte"
import { getContext } from "svelte"
const { columns, config, filter, table } = getContext("grid")
const { columns, tableId, filter, table } = getContext("grid")
const onFilter = e => {
filter.set(e.detail || [])
}
</script>
{#key $config.tableId}
{#key $tableId}
<TableFilterButton
schema={$table?.schema}
filters={$filter}
on:change={onFilter}
disabled={!$columns.length}
tableId={$config.tableId}
tableId={$tableId}
/>
{/key}

View File

@ -2,7 +2,7 @@
import ManageAccessButton from "../ManageAccessButton.svelte"
import { getContext } from "svelte"
const { config } = getContext("grid")
const { tableId } = getContext("grid")
</script>
<ManageAccessButton resourceId={$config.tableId} />
<ManageAccessButton resourceId={$tableId} />

View File

@ -70,7 +70,15 @@
</div>
{/if}
{/if}
{#if $config.allowExpandRows}
{#if rowSelected && $config.allowDeleteRows}
<div class="delete" on:click={() => dispatch("request-bulk-delete")}>
<Icon
name="Delete"
size="S"
color="var(--spectrum-global-color-red-400)"
/>
</div>
{:else if $config.allowExpandRows}
<div
class="expand"
class:visible={!disableExpand && (rowFocused || rowHovered)}
@ -111,9 +119,12 @@
.number.visible {
display: flex;
}
.delete,
.expand {
margin-right: 4px;
}
.expand {
opacity: 0;
margin-right: 4px;
}
.expand :global(.spectrum-Icon) {
pointer-events: none;
@ -124,4 +135,11 @@
.expand.visible :global(.spectrum-Icon) {
pointer-events: all;
}
.delete:hover {
cursor: pointer;
}
.delete:hover :global(.spectrum-Icon) {
color: var(--spectrum-global-color-red-600) !important;
}
</style>

View File

@ -1,8 +1,8 @@
<script>
import { Modal, ModalContent, Button, notifications } from "@budibase/bbui"
import { Modal, ModalContent, notifications } from "@budibase/bbui"
import { getContext, onMount } from "svelte"
const { selectedRows, rows, config, subscribe } = getContext("grid")
const { selectedRows, rows, subscribe } = getContext("grid")
let modal
@ -27,20 +27,6 @@
onMount(() => subscribe("request-bulk-delete", () => modal?.show()))
</script>
{#if selectedRowCount}
<div class="delete-button" data-ignore-click-outside="true">
<Button
icon="Delete"
size="M"
on:click={modal.show}
disabled={!$config.allowEditRows}
cta
>
Delete {selectedRowCount} row{selectedRowCount === 1 ? "" : "s"}
</Button>
</div>
{/if}
<Modal bind:this={modal}>
<ModalContent
title="Delete rows"
@ -53,14 +39,3 @@
row{selectedRowCount === 1 ? "" : "s"}?
</ModalContent>
</Modal>
<style>
.delete-button :global(.spectrum-Button:not(:disabled)) {
background-color: var(--spectrum-global-color-red-400);
border-color: var(--spectrum-global-color-red-400);
}
.delete-button :global(.spectrum-Button:not(:disabled):hover) {
background-color: var(--spectrum-global-color-red-500);
border-color: var(--spectrum-global-color-red-500);
}
</style>

View File

@ -3,7 +3,7 @@
import { ActionButton, Popover } from "@budibase/bbui"
import { DefaultColumnWidth } from "../lib/constants"
const { stickyColumn, columns } = getContext("grid")
const { stickyColumn, columns, compact } = getContext("grid")
const smallSize = 120
const mediumSize = DefaultColumnWidth
const largeSize = DefaultColumnWidth * 1.5
@ -59,12 +59,13 @@
on:click={() => (open = !open)}
selected={open}
disabled={!allCols.length}
tooltip={$compact ? "Width" : null}
>
Width
{$compact ? "" : "Width"}
</ActionButton>
</div>
<Popover bind:open {anchor} align="left">
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content">
{#each sizeOptions as option}
<ActionButton

View File

@ -1,8 +1,9 @@
<script>
import { getContext } from "svelte"
import { ActionButton, Popover, Toggle } from "@budibase/bbui"
import { ActionButton, Popover, Toggle, Icon } from "@budibase/bbui"
import { getColumnIcon } from "../lib/utils"
const { columns, stickyColumn } = getContext("grid")
const { columns, stickyColumn, compact } = getContext("grid")
let open = false
let anchor
@ -47,25 +48,32 @@
on:click={() => (open = !open)}
selected={open || anyHidden}
disabled={!$columns.length}
tooltip={$compact ? "Columns" : ""}
>
Columns
{$compact ? "" : "Columns"}
</ActionButton>
</div>
<Popover bind:open {anchor} align="left">
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content">
<div class="columns">
{#if $stickyColumn}
<div class="column">
<Icon size="S" name={getColumnIcon($stickyColumn)} />
{$stickyColumn.label}
</div>
<Toggle disabled size="S" value={true} />
<span>{$stickyColumn.label}</span>
{/if}
{#each $columns as column}
<div class="column">
<Icon size="S" name={getColumnIcon(column)} />
{column.label}
</div>
<Toggle
size="S"
value={column.visible}
on:change={e => toggleVisibility(column, e.detail)}
/>
<span>{column.label}</span>
{/each}
</div>
<div class="buttons">
@ -90,6 +98,13 @@
.columns {
display: grid;
align-items: center;
grid-template-columns: auto 1fr;
grid-template-columns: 1fr auto;
}
.columns :global(.spectrum-Switch) {
margin-right: 0;
}
.column {
display: flex;
gap: 8px;
}
</style>

View File

@ -7,7 +7,7 @@
SmallRowHeight,
} from "../lib/constants"
const { rowHeight, columns, table } = getContext("grid")
const { rowHeight, columns, table, compact } = getContext("grid")
const sizeOptions = [
{
label: "Small",
@ -41,12 +41,13 @@
size="M"
on:click={() => (open = !open)}
selected={open}
tooltip={$compact ? "Height" : null}
>
Height
{$compact ? "" : "Height"}
</ActionButton>
</div>
<Popover bind:open {anchor} align="left">
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content">
{#each sizeOptions as option}
<ActionButton

View File

@ -2,7 +2,7 @@
import { getContext } from "svelte"
import { ActionButton, Popover, Select } from "@budibase/bbui"
const { sort, columns, stickyColumn } = getContext("grid")
const { sort, columns, stickyColumn, compact } = getContext("grid")
let open = false
let anchor
@ -90,12 +90,13 @@
on:click={() => (open = !open)}
selected={open}
disabled={!columnOptions.length}
tooltip={$compact ? "Sort" : ""}
>
Sort
{$compact ? "" : "Sort"}
</ActionButton>
</div>
<Popover bind:open {anchor} align="left">
<Popover bind:open {anchor} align={$compact ? "right" : "left"}>
<div class="content">
<Select
placeholder={null}

View File

@ -6,7 +6,7 @@
import { createEventManagers } from "../lib/events"
import { createAPIClient } from "../../../api"
import { attachStores } from "../stores"
import DeleteButton from "../controls/DeleteButton.svelte"
import BulkDeleteHandler from "../controls/BulkDeleteHandler.svelte"
import BetaButton from "../controls/BetaButton.svelte"
import GridBody from "./GridBody.svelte"
import ResizeOverlay from "../overlays/ResizeOverlay.svelte"
@ -112,13 +112,12 @@
<AddRowButton />
<AddColumnButton />
<slot name="controls" />
<SortButton />
<HideColumnsButton />
<ColumnWidthButton />
<RowHeightButton />
<HideColumnsButton />
<SortButton />
</div>
<div class="controls-right">
<DeleteButton />
<UserAvatars />
</div>
</div>
@ -131,7 +130,9 @@
<GridBody />
</div>
<BetaButton />
<NewRow />
{#if allowAddRows}
<NewRow />
{/if}
<div class="overlays">
<ResizeOverlay />
<ReorderOverlay />
@ -146,6 +147,9 @@
<ProgressCircle />
</div>
{/if}
{#if allowDeleteRows}
<BulkDeleteHandler />
{/if}
<KeyboardManager />
</div>
@ -214,6 +218,7 @@
padding: var(--cell-padding);
gap: var(--cell-spacing);
background: var(--background);
z-index: 2;
}
.controls-left,
.controls-right {
@ -239,7 +244,7 @@
height: 100%;
display: grid;
place-items: center;
z-index: 10;
z-index: 100;
}
.grid-loading:before {
content: "";

View File

@ -4,8 +4,14 @@
import HeaderCell from "../cells/HeaderCell.svelte"
import { Icon } from "@budibase/bbui"
const { renderedColumns, dispatch, scroll, hiddenColumnsWidth, width } =
getContext("grid")
const {
renderedColumns,
dispatch,
scroll,
hiddenColumnsWidth,
width,
config,
} = getContext("grid")
$: columnsWidth = $renderedColumns.reduce(
(total, col) => (total += col.width),
@ -23,13 +29,15 @@
{/each}
</div>
</GridScrollWrapper>
<div
class="add"
style="left:{left}px"
on:click={() => dispatch("add-column")}
>
<Icon name="Add" />
</div>
{#if $config.allowAddColumns}
<div
class="add"
style="left:{left}px"
on:click={() => dispatch("add-column")}
>
<Icon name="Add" />
</div>
{/if}
</div>
<style>
@ -38,7 +46,6 @@
border-bottom: var(--cell-border);
position: relative;
height: var(--default-row-height);
z-index: 1;
}
.row {
display: flex;
@ -54,6 +61,7 @@
border-right: var(--cell-border);
border-bottom: var(--cell-border);
background: var(--spectrum-global-color-gray-100);
z-index: 20;
}
.add:hover {
background: var(--spectrum-global-color-gray-200);

View File

@ -270,7 +270,7 @@
z-index: 3;
position: absolute;
top: calc(var(--row-height) + var(--offset) + 24px);
left: var(--gutter-width);
left: 18px;
}
.button-with-keys {
display: flex;

View File

@ -21,6 +21,9 @@ const TypeIconMap = {
}
export const getColumnIcon = column => {
if (column.schema.autocolumn) {
return "MagicWand"
}
const type = column.schema.type
return TypeIconMap[type] || "Text"
}

View File

@ -13,6 +13,7 @@
clipboard,
dispatch,
selectedRows,
config,
} = getContext("grid")
const ignoredOriginSelectors = [
@ -37,10 +38,12 @@
e.preventDefault()
focusFirstCell()
} else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
e.preventDefault()
dispatch("add-row-inline")
if ($config.allowAddRows) {
e.preventDefault()
dispatch("add-row-inline")
}
} else if (e.key === "Delete" || e.key === "Backspace") {
if (Object.keys($selectedRows).length) {
if (Object.keys($selectedRows).length && $config.allowDeleteRows) {
dispatch("request-bulk-delete")
}
}
@ -88,7 +91,9 @@
}
break
case "Enter":
dispatch("add-row-inline")
if ($config.allowAddRows) {
dispatch("add-row-inline")
}
}
} else {
switch (e.key) {
@ -106,7 +111,7 @@
break
case "Delete":
case "Backspace":
if (Object.keys($selectedRows).length) {
if (Object.keys($selectedRows).length && $config.allowDeleteRows) {
dispatch("request-bulk-delete")
} else {
deleteSelectedCell()
@ -117,7 +122,9 @@
break
case " ":
case "Space":
toggleSelectRow()
if ($config.allowDeleteRows) {
toggleSelectRow()
}
break
default:
startEnteringValue(e.key, e.which)

View File

@ -2,6 +2,7 @@ import { writable, get, derived } from "svelte/store"
import { tick } from "svelte"
import {
DefaultRowHeight,
GutterWidth,
LargeRowHeight,
MediumRowHeight,
NewRowID,
@ -43,6 +44,8 @@ export const deriveStores = context => {
enrichedRows,
rowLookupMap,
rowHeight,
stickyColumn,
width,
} = context
// Derive the row that contains the selected cell
@ -70,6 +73,7 @@ export const deriveStores = context => {
hoveredRowId.set(null)
}
// Derive the amount of content lines to show in cells depending on row height
const contentLines = derived(rowHeight, $rowHeight => {
if ($rowHeight === LargeRowHeight) {
return 3
@ -79,9 +83,15 @@ export const deriveStores = context => {
return 1
})
// Derive whether we should use the compact UI, depending on width
const compact = derived([stickyColumn, width], ([$stickyColumn, $width]) => {
return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
})
return {
focusedRow,
contentLines,
compact,
ui: {
actions: {
blur,