Update new row component to render inline where possible

This commit is contained in:
Andrew Kingston 2023-04-24 12:50:35 +01:00
parent 98430138fe
commit 5cbaf2f58a
7 changed files with 74 additions and 57 deletions

View File

@ -27,12 +27,6 @@
// Get the error for this cell if the row is focused
$: error = getErrorStore(rowFocused, cellId)
$: {
if ($error) {
console.log(cellId, $error)
}
}
// Determine if the cell is editable
$: readonly =
column.schema.autocolumn ||

View File

@ -45,7 +45,7 @@
style="width:{renderColumnsWidth}px"
on:mouseenter={() => ($hoveredRowId = BlankRowID)}
on:mouseleave={() => ($hoveredRowId = null)}
on:click={() => dispatch("add-row-inline", true)}
on:click={() => dispatch("add-row-inline")}
/>
{/if}
</GridScrollWrapper>

View File

@ -1,5 +1,4 @@
<script>
import GridCell from "../cells/GridCell.svelte"
import { getContext, onDestroy, onMount, tick } from "svelte"
import { Icon, Button } from "@budibase/bbui"
import GridScrollWrapper from "./GridScrollWrapper.svelte"
@ -14,18 +13,23 @@
focusedCellId,
stickyColumn,
scroll,
config,
dispatch,
rows,
focusedCellAPI,
tableId,
subscribe,
renderedRows,
renderedColumns,
rowHeight,
hasNextPage,
maxScrollTop,
} = getContext("grid")
let isAdding = false
let newRow = {}
let offset = 0
$: minimumDesiredRenderHeight = $rowHeight + 96
$: firstColumn = $stickyColumn || $renderedColumns[0]
$: width = GutterWidth + ($stickyColumn?.width || 0)
$: $tableId, (isAdding = false)
@ -36,13 +40,10 @@
await tick()
// Create row
const savedRow = await rows.actions.addRow(newRow, 0)
const newRowIndex = offset ? undefined : 0
const savedRow = await rows.actions.addRow(newRow, newRowIndex)
if (savedRow) {
// Reset state
scroll.update(state => ({
...state,
top: 0,
}))
clear()
// Select the first cell if possible
@ -63,6 +64,24 @@
if (isAdding) {
return
}
// If we have a next page of data then we aren't truly at the bottom, so we
// render the add row component at the top
if ($hasNextPage) {
offset = 0
}
// If we don't have a next page then we're at the bottom and can scroll to
// the max available offset
else {
scroll.update(state => ({
...state,
top: $maxScrollTop,
}))
offset =
$renderedRows.length * $rowHeight - ($maxScrollTop % $rowHeight) - 1
}
document.addEventListener("keydown", handleKeyPress)
newRow = {}
isAdding = true
@ -105,7 +124,11 @@
<!-- Only show new row functionality if we have any columns -->
{#if isAdding}
<div class="container">
<div
class="container"
class:floating={offset > 0}
style="--offset:{offset}px"
>
<div
class="underlay sticky"
style="width:{width}px;"
@ -134,25 +157,27 @@
/>
{/if}
</div>
<GridScrollWrapper scrollHorizontally wheelInteractive>
<div class="row" transition:fade={{ duration: 130 }}>
{#each $renderedColumns as column}
{@const cellId = `new-${column.name}`}
{#key cellId}
<DataCell
{cellId}
{column}
{updateValue}
rowFocused
row={newRow}
focused={$focusedCellId === cellId}
width={column.width}
rowIdx={0}
/>
{/key}
{/each}
</div>
</GridScrollWrapper>
<div class="normal-columns">
<GridScrollWrapper scrollHorizontally wheelInteractive>
<div class="row" transition:fade={{ duration: 130 }}>
{#each $renderedColumns as column}
{@const cellId = `new-${column.name}`}
{#key cellId}
<DataCell
{cellId}
{column}
{updateValue}
rowFocused
row={newRow}
focused={$focusedCellId === cellId}
width={column.width}
rowIdx={0}
/>
{/key}
{/each}
</div>
</GridScrollWrapper>
</div>
<div class="buttons" transition:fade={{ duration: 130 }}>
<Button size="M" cta on:click={addRow}>Save</Button>
<Button size="M" secondary newStyles on:click={clear}>Cancel</Button>
@ -174,13 +199,17 @@
.container :global(.cell) {
--cell-background: var(--spectrum-global-color-gray-75) !important;
}
.container.floating :global(.cell) {
height: calc(var(--row-height) + 1px);
border-top: var(--cell-border);
}
/* Underlay sits behind everything */
.underlay {
position: absolute;
content: "";
left: 0;
top: var(--row-height);
top: 0;
height: 100%;
width: 100%;
background: var(--cell-background);
@ -198,8 +227,8 @@
pointer-events: all;
z-index: 3;
position: absolute;
top: calc(var(--row-height) + 24px);
left: 32px;
top: calc(var(--row-height) + var(--offset) + 24px);
left: var(--gutter-width);
}
/* Sticky column styles */
@ -212,20 +241,9 @@
.sticky-column :global(.cell:not(:last-child)) {
border-right: none;
}
.gutter {
flex: 1 1 auto;
display: grid;
align-items: center;
padding: var(--cell-padding);
grid-template-columns: 1fr auto;
gap: var(--cell-spacing);
}
.number {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
color: var(--spectrum-global-color-gray-500);
.sticky-column,
.normal-columns {
margin-top: var(--offset);
}
/* Normal column styles */

View File

@ -91,7 +91,7 @@
class="row new"
on:mouseenter={() => ($hoveredRowId = BlankRowID)}
on:mouseleave={() => ($hoveredRowId = null)}
on:click={() => dispatch("add-row-inline", true)}
on:click={() => dispatch("add-row-inline")}
>
<GutterCell disableExpand rowHovered={$hoveredRowId === BlankRowID}>
<Icon name="Add" />

View File

@ -1,4 +1,4 @@
export const Padding = 276
export const Padding = 128
export const MaxCellRenderHeight = 252
export const MaxCellRenderWidthOverflow = 200
export const ScrollBarSize = 8
@ -11,3 +11,4 @@ export const LargeRowHeight = 92
export const DefaultRowHeight = SmallRowHeight
export const NewRowID = "new"
export const BlankRowID = "blank"
export const RowPageSize = 100

View File

@ -1,7 +1,7 @@
import { writable, derived, get } from "svelte/store"
import { fetchData } from "../../../fetch/fetchData"
import { notifications } from "@budibase/bbui"
import { NewRowID } from "../lib/constants"
import { NewRowID, RowPageSize } from "../lib/constants"
const initialSortState = {
column: null,
@ -17,6 +17,7 @@ export const createStores = () => {
const sort = writable(initialSortState)
const rowChangeCache = writable({})
const inProgressChanges = writable({})
const hasNextPage = writable(false)
// Generate a lookup map to quick find a row by ID
const rowLookupMap = derived(
@ -51,6 +52,7 @@ export const createStores = () => {
sort,
rowChangeCache,
inProgressChanges,
hasNextPage,
}
}
@ -71,6 +73,7 @@ export const deriveStores = context => {
rowChangeCache,
inProgressChanges,
previousFocusedRowId,
hasNextPage,
} = context
const instanceLoaded = writable(false)
const fetch = writable(null)
@ -115,7 +118,7 @@ export const deriveStores = context => {
filter: [],
sortColumn: initialSortState.column,
sortOrder: initialSortState.order,
limit: 100,
limit: RowPageSize,
paginate: true,
},
})
@ -123,6 +126,7 @@ export const deriveStores = context => {
// Subscribe to changes of this fetch model
unsubscribe = newFetch.subscribe($fetch => {
if ($fetch.loaded && !$fetch.loading) {
hasNextPage.set($fetch.hasNextPage)
const $instanceLoaded = get(instanceLoaded)
const resetRows = $fetch.resetKey !== lastResetKey
lastResetKey = $fetch.resetKey

View File

@ -29,7 +29,7 @@ export const deriveStores = context => {
// Derive vertical limits
const contentHeight = derived(
[rows, rowHeight],
([$rows, $rowHeight]) => $rows.length * $rowHeight + Padding,
([$rows, $rowHeight]) => ($rows.length + 1) * $rowHeight + Padding,
0
)
const maxScrollTop = derived(
@ -138,7 +138,7 @@ export const initialise = context => {
const $scroll = get(scroll)
const $bounds = get(bounds)
const $rowHeight = get(rowHeight)
const verticalOffset = DefaultRowHeight * 1.5
const verticalOffset = 60
// Ensure vertical position is viewable
if ($focusedRow) {