WIP
This commit is contained in:
parent
0d2cef20df
commit
ada3367b49
|
@ -270,7 +270,7 @@
|
|||
on:touchcancel={onMouseUp}
|
||||
on:contextmenu={onContextMenu}
|
||||
width={column.width}
|
||||
left={column.left}
|
||||
left={column.__left}
|
||||
defaultHeight
|
||||
center
|
||||
>
|
||||
|
|
|
@ -7,14 +7,12 @@
|
|||
|
||||
export let allowViewReadonlyColumns = false
|
||||
|
||||
const { columns, datasource, stickyColumn, dispatch } = getContext("grid")
|
||||
const { columns, datasource, dispatch } = getContext("grid")
|
||||
|
||||
let open = false
|
||||
let anchor
|
||||
|
||||
$: allColumns = $stickyColumn ? [$stickyColumn, ...$columns] : $columns
|
||||
|
||||
$: restrictedColumns = allColumns.filter(col => !col.visible || col.readonly)
|
||||
$: restrictedColumns = $columns.filter(col => !col.visible || col.readonly)
|
||||
$: anyRestricted = restrictedColumns.length
|
||||
$: text = anyRestricted ? `Columns (${anyRestricted} restricted)` : "Columns"
|
||||
|
||||
|
@ -43,12 +41,9 @@
|
|||
HIDDEN: "hidden",
|
||||
}
|
||||
|
||||
$: displayColumns = allColumns.map(c => {
|
||||
$: displayColumns = $columns.map(c => {
|
||||
const isRequired = helpers.schema.isRequired(c.schema.constraints)
|
||||
const isDisplayColumn = $stickyColumn === c
|
||||
|
||||
const requiredTooltip = isRequired && "Required columns must be writable"
|
||||
|
||||
const editEnabled =
|
||||
!isRequired ||
|
||||
columnToPermissionOptions(c) !== PERMISSION_OPTIONS.WRITABLE
|
||||
|
@ -74,9 +69,9 @@
|
|||
options.push({
|
||||
icon: "VisibilityOff",
|
||||
value: PERMISSION_OPTIONS.HIDDEN,
|
||||
disabled: isDisplayColumn || isRequired,
|
||||
disabled: c.primaryDisplay || isRequired,
|
||||
tooltip:
|
||||
(isDisplayColumn && "Display column cannot be hidden") ||
|
||||
(c.primaryDisplay && "Display column cannot be hidden") ||
|
||||
requiredTooltip ||
|
||||
"Hidden",
|
||||
})
|
||||
|
|
|
@ -8,14 +8,8 @@
|
|||
SmallRowHeight,
|
||||
} from "../lib/constants"
|
||||
|
||||
const {
|
||||
stickyColumn,
|
||||
columns,
|
||||
rowHeight,
|
||||
definition,
|
||||
fixedRowHeight,
|
||||
datasource,
|
||||
} = getContext("grid")
|
||||
const { columns, rowHeight, definition, fixedRowHeight, datasource } =
|
||||
getContext("grid")
|
||||
|
||||
// Some constants for column width options
|
||||
const smallColSize = 120
|
||||
|
@ -42,10 +36,9 @@
|
|||
let anchor
|
||||
|
||||
// Column width sizes
|
||||
$: allCols = $columns.concat($stickyColumn ? [$stickyColumn] : [])
|
||||
$: allSmall = allCols.every(col => col.width === smallColSize)
|
||||
$: allMedium = allCols.every(col => col.width === mediumColSize)
|
||||
$: allLarge = allCols.every(col => col.width === largeColSize)
|
||||
$: allSmall = $columns.every(col => col.width === smallColSize)
|
||||
$: allMedium = $columns.every(col => col.width === mediumColSize)
|
||||
$: allLarge = $columns.every(col => col.width === largeColSize)
|
||||
$: custom = !allSmall && !allMedium && !allLarge
|
||||
$: columnSizeOptions = [
|
||||
{
|
||||
|
@ -80,7 +73,7 @@
|
|||
size="M"
|
||||
on:click={() => (open = !open)}
|
||||
selected={open}
|
||||
disabled={!allCols.length}
|
||||
disabled={!$columns.length}
|
||||
>
|
||||
Size
|
||||
</ActionButton>
|
||||
|
|
|
@ -3,33 +3,19 @@
|
|||
import { ActionButton, Popover, Select } from "@budibase/bbui"
|
||||
import { canBeSortColumn } from "@budibase/shared-core"
|
||||
|
||||
const { sort, columns, stickyColumn } = getContext("grid")
|
||||
const { sort, columns } = getContext("grid")
|
||||
|
||||
let open = false
|
||||
let anchor
|
||||
|
||||
$: columnOptions = getColumnOptions($stickyColumn, $columns)
|
||||
$: orderOptions = getOrderOptions($sort.column, columnOptions)
|
||||
|
||||
const getColumnOptions = (stickyColumn, columns) => {
|
||||
let options = []
|
||||
if (stickyColumn) {
|
||||
options.push({
|
||||
label: stickyColumn.label || stickyColumn.name,
|
||||
value: stickyColumn.name,
|
||||
type: stickyColumn.schema?.type,
|
||||
})
|
||||
}
|
||||
options = [
|
||||
...options,
|
||||
...columns.map(col => ({
|
||||
$: columnOptions = $columns
|
||||
.map(col => ({
|
||||
label: col.label || col.name,
|
||||
value: col.name,
|
||||
type: col.schema?.type,
|
||||
})),
|
||||
]
|
||||
return options.filter(col => canBeSortColumn(col.type))
|
||||
}
|
||||
}))
|
||||
.filter(col => canBeSortColumn(col.type))
|
||||
$: orderOptions = getOrderOptions($sort.column, columnOptions)
|
||||
|
||||
const getOrderOptions = (column, columnOptions) => {
|
||||
const type = columnOptions.find(col => col.value === column)?.type
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
const {
|
||||
bounds,
|
||||
renderedRows,
|
||||
visibleColumns,
|
||||
scrollableColumns,
|
||||
hoveredRowId,
|
||||
dispatch,
|
||||
isDragging,
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
let body
|
||||
|
||||
$: columnsWidth = $visibleColumns.reduce(
|
||||
$: columnsWidth = $scrollableColumns.reduce(
|
||||
(total, col) => (total += col.width),
|
||||
0
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
focusedCellId,
|
||||
reorder,
|
||||
selectedRows,
|
||||
visibleColumns,
|
||||
scrollableColumns,
|
||||
hoveredRowId,
|
||||
focusedRow,
|
||||
contentLines,
|
||||
|
@ -40,7 +40,7 @@
|
|||
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
||||
on:click={() => dispatch("rowclick", rows.actions.cleanRow(row))}
|
||||
>
|
||||
{#each $visibleColumns as column}
|
||||
{#each $scrollableColumns as column}
|
||||
{@const cellId = getCellID(row._id, column.name)}
|
||||
<DataCell
|
||||
{cellId}
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
import HeaderCell from "../cells/HeaderCell.svelte"
|
||||
import { TempTooltip, TooltipType } from "@budibase/bbui"
|
||||
|
||||
const { visibleColumns, config, hasNonAutoColumn, datasource, loading } =
|
||||
const { scrollableColumns, config, hasNonAutoColumn, datasource, loading } =
|
||||
getContext("grid")
|
||||
</script>
|
||||
|
||||
<div class="header">
|
||||
<GridScrollWrapper scrollHorizontally>
|
||||
<div class="row">
|
||||
{#each $visibleColumns as column, idx}
|
||||
{#each $scrollableColumns as column, idx}
|
||||
<HeaderCell {column} {idx}>
|
||||
<slot name="edit-column" />
|
||||
</HeaderCell>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
const {
|
||||
hoveredRowId,
|
||||
focusedCellId,
|
||||
stickyColumn,
|
||||
displayColumn,
|
||||
scroll,
|
||||
dispatch,
|
||||
rows,
|
||||
|
@ -38,8 +38,8 @@
|
|||
let newRow
|
||||
let offset = 0
|
||||
|
||||
$: firstColumn = $stickyColumn || $visibleColumns[0]
|
||||
$: width = GutterWidth + ($stickyColumn?.width || 0)
|
||||
$: firstColumn = $visibleColumns[0]
|
||||
$: width = GutterWidth + ($displayColumn?.width || 0)
|
||||
$: $datasource, (visible = false)
|
||||
$: selectedRowCount = Object.values($selectedRows).length
|
||||
$: hasNoRows = !$rows.length
|
||||
|
@ -164,7 +164,7 @@
|
|||
class="new-row-fab"
|
||||
on:click={() => dispatch("add-row-inline")}
|
||||
transition:fade|local={{ duration: 130 }}
|
||||
class:offset={!$stickyColumn}
|
||||
class:offset={!$displayColumn}
|
||||
>
|
||||
<Icon name="Add" size="S" />
|
||||
</div>
|
||||
|
@ -187,19 +187,19 @@
|
|||
<div in:fade={{ duration: 130 }} class="loading-overlay" />
|
||||
{/if}
|
||||
</GutterCell>
|
||||
{#if $stickyColumn}
|
||||
{@const cellId = getCellID(NewRowID, $stickyColumn.name)}
|
||||
{#if $displayColumn}
|
||||
{@const cellId = getCellID(NewRowID, $displayColumn.name)}
|
||||
<DataCell
|
||||
{cellId}
|
||||
rowFocused
|
||||
column={$stickyColumn}
|
||||
column={$displayColumn}
|
||||
row={newRow}
|
||||
focused={$focusedCellId === cellId}
|
||||
width={$stickyColumn.width}
|
||||
width={$displayColumn.width}
|
||||
{updateValue}
|
||||
topRow={offset === 0}
|
||||
>
|
||||
{#if $stickyColumn?.schema?.autocolumn}
|
||||
{#if $displayColumn?.schema?.autocolumn}
|
||||
<div class="readonly-overlay">Can't edit auto column</div>
|
||||
{/if}
|
||||
{#if isAdding}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
const {
|
||||
rows,
|
||||
selectedRows,
|
||||
stickyColumn,
|
||||
displayColumn,
|
||||
renderedRows,
|
||||
focusedCellId,
|
||||
hoveredRowId,
|
||||
|
@ -26,13 +26,12 @@
|
|||
contentLines,
|
||||
isDragging,
|
||||
isSelectingCells,
|
||||
selectedCells,
|
||||
selectedCellCount,
|
||||
} = getContext("grid")
|
||||
|
||||
$: rowCount = $rows.length
|
||||
$: selectedRowCount = Object.values($selectedRows).length
|
||||
$: width = GutterWidth + ($stickyColumn?.width || 0)
|
||||
$: width = GutterWidth + ($displayColumn?.width || 0)
|
||||
|
||||
const selectAll = () => {
|
||||
const allSelected = selectedRowCount === rowCount
|
||||
|
@ -61,8 +60,8 @@
|
|||
rowSelected={selectedRowCount && selectedRowCount === rowCount}
|
||||
disabled={!$renderedRows.length}
|
||||
/>
|
||||
{#if $stickyColumn}
|
||||
<HeaderCell column={$stickyColumn} orderable={false} idx="sticky">
|
||||
{#if $displayColumn}
|
||||
<HeaderCell column={$displayColumn} orderable={false} idx="sticky">
|
||||
<slot name="edit-column" />
|
||||
</HeaderCell>
|
||||
{/if}
|
||||
|
@ -78,7 +77,7 @@
|
|||
$hoveredRowId === row._id &&
|
||||
(!$selectedCellCount || !$isSelectingCells)}
|
||||
{@const rowFocused = $focusedRow?._id === row._id}
|
||||
{@const cellId = getCellID(row._id, $stickyColumn?.name)}
|
||||
{@const cellId = getCellID(row._id, $displayColumn?.name)}
|
||||
<div
|
||||
class="row"
|
||||
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
||||
|
@ -86,7 +85,7 @@
|
|||
on:click={() => dispatch("rowclick", rows.actions.cleanRow(row))}
|
||||
>
|
||||
<GutterCell {row} {rowFocused} {rowHovered} {rowSelected} />
|
||||
{#if $stickyColumn}
|
||||
{#if $displayColumn}
|
||||
<DataCell
|
||||
{row}
|
||||
{cellId}
|
||||
|
@ -98,8 +97,8 @@
|
|||
topRow={idx === 0}
|
||||
focused={$focusedCellId === cellId}
|
||||
selectedUser={$userCellMap[cellId]}
|
||||
width={$stickyColumn.width}
|
||||
column={$stickyColumn}
|
||||
width={$displayColumn.width}
|
||||
column={$displayColumn}
|
||||
contentLines={$contentLines}
|
||||
isSelectingCells={$isSelectingCells}
|
||||
/>
|
||||
|
@ -118,9 +117,9 @@
|
|||
<GutterCell rowHovered={$hoveredRowId === BlankRowID}>
|
||||
<Icon name="Add" color="var(--spectrum-global-color-gray-500)" />
|
||||
</GutterCell>
|
||||
{#if $stickyColumn}
|
||||
{#if $displayColumn}
|
||||
<GridCell
|
||||
width={$stickyColumn.width}
|
||||
width={$displayColumn.width}
|
||||
highlighted={$hoveredRowId === BlankRowID}
|
||||
>
|
||||
<KeyboardShortcut padded keybind="Ctrl+Enter" />
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
focusedCellId,
|
||||
visibleColumns,
|
||||
rowLookupMap,
|
||||
stickyColumn,
|
||||
focusedCellAPI,
|
||||
dispatch,
|
||||
selectedRowCount,
|
||||
|
@ -168,7 +167,7 @@
|
|||
if (!firstRow) {
|
||||
return
|
||||
}
|
||||
const firstColumn = $stickyColumn || $visibleColumns[0]
|
||||
const firstColumn = $visibleColumns[0]
|
||||
if (!firstColumn) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -6,30 +6,30 @@
|
|||
const {
|
||||
isReordering,
|
||||
reorder,
|
||||
visibleColumns,
|
||||
stickyColumn,
|
||||
visibleColumnLookupMap,
|
||||
displayColumn,
|
||||
rowHeight,
|
||||
renderedRows,
|
||||
scrollLeft,
|
||||
} = getContext("grid")
|
||||
|
||||
$: targetColumn = $reorder.targetColumn
|
||||
$: minLeft = GutterWidth + ($stickyColumn?.width || 0)
|
||||
$: left = getLeft(targetColumn, $stickyColumn, $visibleColumns, $scrollLeft)
|
||||
$: targetColumn = $visibleColumnLookupMap[$reorder.targetColumn]
|
||||
$: console.log(targetColumn)
|
||||
$: minLeft = GutterWidth + ($displayColumn?.width || 0)
|
||||
$: left = getLeft(targetColumn, $displayColumn, $scrollLeft)
|
||||
$: height = $rowHeight * $renderedRows.length + DefaultRowHeight
|
||||
$: style = `left:${left}px; height:${height}px;`
|
||||
$: visible = $isReordering && left >= minLeft
|
||||
|
||||
const getLeft = (targetColumn, stickyColumn, visibleColumns, scrollLeft) => {
|
||||
let left = GutterWidth + (stickyColumn?.width || 0) - scrollLeft
|
||||
const getLeft = (targetColumn, displayColumn, scrollLeft) => {
|
||||
if (!targetColumn) {
|
||||
return 0
|
||||
}
|
||||
let left = GutterWidth + (displayColumn?.width || 0) - scrollLeft
|
||||
|
||||
// If this is not the sticky column, add additional left space
|
||||
if (targetColumn !== stickyColumn?.name) {
|
||||
const column = visibleColumns.find(x => x.name === targetColumn)
|
||||
if (!column) {
|
||||
return left
|
||||
}
|
||||
left += column.left + column.width
|
||||
if (!targetColumn.primaryDisplay) {
|
||||
left += targetColumn.__left + targetColumn.width
|
||||
}
|
||||
|
||||
return left
|
||||
|
|
|
@ -2,28 +2,28 @@
|
|||
import { getContext } from "svelte"
|
||||
import { GutterWidth } from "../lib/constants"
|
||||
|
||||
const { resize, visibleColumns, stickyColumn, isReordering, scrollLeft } =
|
||||
const { resize, visibleColumns, displayColumn, isReordering, scrollLeft } =
|
||||
getContext("grid")
|
||||
|
||||
$: offset = GutterWidth + ($stickyColumn?.width || 0)
|
||||
$: offset = GutterWidth + ($displayColumn?.width || 0)
|
||||
$: activeColumn = $resize.column
|
||||
|
||||
const getStyle = (column, offset, scrollLeft) => {
|
||||
const left = offset + column.left + column.width - scrollLeft
|
||||
const left = offset + column.__left + column.width - scrollLeft
|
||||
return `left:${left}px;`
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
{#if !$isReordering}
|
||||
{#if $stickyColumn}
|
||||
{#if $displayColumn}
|
||||
<div
|
||||
class="resize-slider"
|
||||
class:visible={activeColumn === $stickyColumn.name}
|
||||
on:mousedown={e => resize.actions.startResizing($stickyColumn, e)}
|
||||
on:touchstart={e => resize.actions.startResizing($stickyColumn, e)}
|
||||
on:dblclick={() => resize.actions.resetSize($stickyColumn)}
|
||||
style="left:{GutterWidth + $stickyColumn.width}px;"
|
||||
class:visible={activeColumn === $displayColumn.name}
|
||||
on:mousedown={e => resize.actions.startResizing($displayColumn, e)}
|
||||
on:touchstart={e => resize.actions.startResizing($displayColumn, e)}
|
||||
on:dblclick={() => resize.actions.resetSize($displayColumn)}
|
||||
style="left:{GutterWidth + $displayColumn.width}px;"
|
||||
>
|
||||
<div class="resize-indicator" />
|
||||
</div>
|
||||
|
|
|
@ -63,7 +63,7 @@ export const createActions = context => {
|
|||
rowChangeCache,
|
||||
rows,
|
||||
focusedCellId,
|
||||
columnLookupMap,
|
||||
visibleColumnLookupMap,
|
||||
allVisibleColumns,
|
||||
} = context
|
||||
|
||||
|
@ -156,9 +156,9 @@ export const createActions = context => {
|
|||
const $focusedCellId = get(focusedCellId)
|
||||
const { rowId, field } = parseCellID($focusedCellId)
|
||||
const $rowLookupMap = get(rowLookupMap)
|
||||
const $columnLookupMap = get(columnLookupMap)
|
||||
const $visibleColumnLookupMap = get(visibleColumnLookupMap)
|
||||
const rowIdx = $rowLookupMap[rowId].__idx
|
||||
const colIdx = $columnLookupMap[field]
|
||||
const colIdx = $visibleColumnLookupMap[field].__idx
|
||||
|
||||
// Get limits of how many rows and columns we're able to paste into
|
||||
const $rows = get(rows)
|
||||
|
|
|
@ -1,98 +1,87 @@
|
|||
import { derived, get, writable } from "svelte/store"
|
||||
import { GutterWidth, DefaultColumnWidth } from "../lib/constants"
|
||||
import { DefaultColumnWidth } from "../lib/constants"
|
||||
|
||||
export const createStores = () => {
|
||||
const columns = writable([])
|
||||
const stickyColumn = writable(null)
|
||||
|
||||
// Derive an enriched version of columns with left offsets and indexes
|
||||
// automatically calculated
|
||||
const enrichedColumns = derived(
|
||||
columns,
|
||||
$columns => {
|
||||
let offset = 0
|
||||
return $columns.map(column => {
|
||||
const enriched = {
|
||||
...column,
|
||||
left: offset,
|
||||
}
|
||||
if (column.visible) {
|
||||
offset += column.width
|
||||
}
|
||||
return enriched
|
||||
const enrichedColumns = derived(columns, $columns => {
|
||||
return $columns.map((col, idx) => ({
|
||||
...col,
|
||||
__idx: idx,
|
||||
}))
|
||||
})
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
// Derived list of columns which have not been explicitly hidden
|
||||
const visibleColumns = derived(
|
||||
enrichedColumns,
|
||||
$columns => {
|
||||
return $columns.filter(col => col.visible)
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
return {
|
||||
columns: {
|
||||
...columns,
|
||||
subscribe: enrichedColumns.subscribe,
|
||||
},
|
||||
stickyColumn,
|
||||
visibleColumns,
|
||||
}
|
||||
}
|
||||
|
||||
export const deriveStores = context => {
|
||||
const { columns, stickyColumn, visibleColumns } = context
|
||||
const { columns } = context
|
||||
|
||||
// Quick access to all columns
|
||||
const allColumns = derived(
|
||||
[columns, stickyColumn],
|
||||
([$columns, $stickyColumn]) => {
|
||||
let allCols = $columns || []
|
||||
if ($stickyColumn) {
|
||||
allCols = [$stickyColumn, ...allCols]
|
||||
}
|
||||
return allCols
|
||||
}
|
||||
)
|
||||
// Derive the primary display column
|
||||
const displayColumn = derived(columns, $columns => {
|
||||
return $columns.find(col => col.primaryDisplay)
|
||||
})
|
||||
|
||||
// Quick access to all visible columns
|
||||
const allVisibleColumns = derived(
|
||||
[visibleColumns, stickyColumn],
|
||||
([$visibleColumns, $stickyColumn]) => {
|
||||
let allCols = $visibleColumns || []
|
||||
if ($stickyColumn) {
|
||||
allCols = [$stickyColumn, ...allCols]
|
||||
// Derive a lookup map for all columns by name
|
||||
const columnLookupMap = derived(columns, $columns => {
|
||||
let map = {}
|
||||
$columns.forEach(column => {
|
||||
map[column.name] = column
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
// Derived list of columns which have not been explicitly hidden, and enrich
|
||||
// with an index so we can easily select nearby columns
|
||||
const visibleColumns = derived(columns, $columns => {
|
||||
let offset = 0
|
||||
return $columns
|
||||
.filter(col => col.visible)
|
||||
.map((column, idx) => {
|
||||
const enriched = {
|
||||
...column,
|
||||
__left: offset,
|
||||
__idx: idx,
|
||||
}
|
||||
return allCols
|
||||
}
|
||||
)
|
||||
offset += column.width
|
||||
return enriched
|
||||
})
|
||||
})
|
||||
|
||||
// Derive a lookup map for visible columns by name
|
||||
const visibleColumnLookupMap = derived(visibleColumns, $visibleColumns => {
|
||||
let map = {}
|
||||
$visibleColumns.forEach(column => {
|
||||
map[column.name] = column
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
// Derive scrollable columns
|
||||
const scrollableColumns = derived(visibleColumns, $visibleColumns => {
|
||||
return $visibleColumns.filter(col => !col.primaryDisplay)
|
||||
})
|
||||
|
||||
// Derive if we have any normal columns
|
||||
const hasNonAutoColumn = derived(allColumns, $allColumns => {
|
||||
const normalCols = $allColumns.filter(column => {
|
||||
const hasNonAutoColumn = derived(columns, $columns => {
|
||||
const normalCols = $columns.filter(column => {
|
||||
return !column.schema?.autocolumn
|
||||
})
|
||||
return normalCols.length > 0
|
||||
})
|
||||
|
||||
// Derive a lookup map for column indices by name
|
||||
const columnLookupMap = derived(allVisibleColumns, $allVisibleColumns => {
|
||||
let map = {}
|
||||
$allVisibleColumns.forEach((column, idx) => {
|
||||
map[column.name] = idx
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
return {
|
||||
allColumns,
|
||||
allVisibleColumns,
|
||||
hasNonAutoColumn,
|
||||
displayColumn,
|
||||
columnLookupMap,
|
||||
visibleColumns,
|
||||
visibleColumnLookupMap,
|
||||
scrollableColumns,
|
||||
hasNonAutoColumn,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +99,7 @@ export const createActions = context => {
|
|||
await datasource.actions.saveSchemaMutations()
|
||||
}
|
||||
|
||||
// Checks if a column is readonly
|
||||
const isReadonly = column => {
|
||||
if (!column?.schema) {
|
||||
return false
|
||||
|
@ -134,49 +124,32 @@ export const createActions = context => {
|
|||
}
|
||||
|
||||
export const initialise = context => {
|
||||
const {
|
||||
definition,
|
||||
columns,
|
||||
stickyColumn,
|
||||
allColumns,
|
||||
enrichedSchema,
|
||||
compact,
|
||||
} = context
|
||||
const { definition, columns, displayColumn, enrichedSchema } = context
|
||||
|
||||
// Merge new schema fields with existing schema in order to preserve widths
|
||||
const processColumns = $enrichedSchema => {
|
||||
if (!$enrichedSchema) {
|
||||
columns.set([])
|
||||
stickyColumn.set(null)
|
||||
return
|
||||
}
|
||||
const $definition = get(definition)
|
||||
const $allColumns = get(allColumns)
|
||||
const $stickyColumn = get(stickyColumn)
|
||||
const $compact = get(compact)
|
||||
const $columns = get(columns)
|
||||
const $displayColumn = get(displayColumn)
|
||||
|
||||
// Find primary display
|
||||
let primaryDisplay
|
||||
const candidatePD = $definition.primaryDisplay || $stickyColumn?.name
|
||||
const candidatePD = $definition.primaryDisplay || $displayColumn?.name
|
||||
if (candidatePD && $enrichedSchema[candidatePD]) {
|
||||
primaryDisplay = candidatePD
|
||||
}
|
||||
|
||||
// Get field list
|
||||
let fields = []
|
||||
Object.keys($enrichedSchema).forEach(field => {
|
||||
if ($compact || field !== primaryDisplay) {
|
||||
fields.push(field)
|
||||
}
|
||||
})
|
||||
|
||||
// Update columns, removing extraneous columns and adding missing ones
|
||||
columns.set(
|
||||
fields
|
||||
Object.keys($enrichedSchema)
|
||||
.map(field => {
|
||||
const fieldSchema = $enrichedSchema[field]
|
||||
const oldColumn = $allColumns?.find(x => x.name === field)
|
||||
return {
|
||||
const oldColumn = $columns?.find(col => col.name === field)
|
||||
let column = {
|
||||
name: field,
|
||||
label: fieldSchema.displayName || field,
|
||||
schema: fieldSchema,
|
||||
|
@ -184,19 +157,24 @@ export const initialise = context => {
|
|||
visible: fieldSchema.visible ?? true,
|
||||
readonly: fieldSchema.readonly,
|
||||
order: fieldSchema.order ?? oldColumn?.order,
|
||||
primaryDisplay: field === primaryDisplay,
|
||||
}
|
||||
// Override a few properties for primary display
|
||||
if (field === primaryDisplay) {
|
||||
column.visible = true
|
||||
column.order = 0
|
||||
column.primaryDisplay = true
|
||||
}
|
||||
return column
|
||||
})
|
||||
.sort((a, b) => {
|
||||
// If we don't have a pinned column then primary display will be in
|
||||
// the normal columns list, and should be first
|
||||
// Display column should always come first
|
||||
if (a.name === primaryDisplay) {
|
||||
return -1
|
||||
} else if (b.name === primaryDisplay) {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Sort by order first
|
||||
// Then sort by order
|
||||
const orderA = a.order
|
||||
const orderB = b.order
|
||||
if (orderA != null && orderB != null) {
|
||||
|
@ -216,29 +194,8 @@ export const initialise = context => {
|
|||
return autoColA ? 1 : -1
|
||||
})
|
||||
)
|
||||
|
||||
// Update sticky column
|
||||
if ($compact || !primaryDisplay) {
|
||||
stickyColumn.set(null)
|
||||
return
|
||||
}
|
||||
const stickySchema = $enrichedSchema[primaryDisplay]
|
||||
const oldStickyColumn = $allColumns?.find(x => x.name === primaryDisplay)
|
||||
stickyColumn.set({
|
||||
name: primaryDisplay,
|
||||
label: stickySchema.displayName || primaryDisplay,
|
||||
schema: stickySchema,
|
||||
width: stickySchema.width || oldStickyColumn?.width || DefaultColumnWidth,
|
||||
visible: true,
|
||||
order: 0,
|
||||
left: GutterWidth,
|
||||
primaryDisplay: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Process columns when schema changes
|
||||
enrichedSchema.subscribe(processColumns)
|
||||
|
||||
// Process columns when compact flag changes
|
||||
compact.subscribe(() => processColumns(get(enrichedSchema)))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { get } from "svelte/store"
|
||||
|
||||
export const createActions = context => {
|
||||
const { columns, stickyColumn, table, viewV2 } = context
|
||||
const { columns, table, viewV2 } = context
|
||||
|
||||
const saveDefinition = async () => {
|
||||
throw "This datasource does not support updating the definition"
|
||||
|
@ -30,9 +30,7 @@ export const createActions = context => {
|
|||
}
|
||||
|
||||
const canUseColumn = name => {
|
||||
const $columns = get(columns)
|
||||
const $sticky = get(stickyColumn)
|
||||
return $columns.some(col => col.name === name) || $sticky?.name === name
|
||||
return get(columns).some(col => col.name === name)
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { get } from "svelte/store"
|
|||
const SuppressErrors = true
|
||||
|
||||
export const createActions = context => {
|
||||
const { API, datasource, columns, stickyColumn } = context
|
||||
const { API, datasource, columns } = context
|
||||
|
||||
const saveDefinition = async newDefinition => {
|
||||
await API.saveTable(newDefinition)
|
||||
|
@ -43,9 +43,7 @@ export const createActions = context => {
|
|||
}
|
||||
|
||||
const canUseColumn = name => {
|
||||
const $columns = get(columns)
|
||||
const $sticky = get(stickyColumn)
|
||||
return $columns.some(col => col.name === name) || $sticky?.name === name
|
||||
return get(columns).some(col => col.name === name)
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { get } from "svelte/store"
|
|||
const SuppressErrors = true
|
||||
|
||||
export const createActions = context => {
|
||||
const { API, datasource, columns, stickyColumn } = context
|
||||
const { API, datasource, columns } = context
|
||||
|
||||
const saveDefinition = async newDefinition => {
|
||||
await API.viewV2.update(newDefinition)
|
||||
|
@ -40,12 +40,7 @@ export const createActions = context => {
|
|||
}
|
||||
|
||||
const canUseColumn = name => {
|
||||
const $columns = get(columns)
|
||||
const $sticky = get(stickyColumn)
|
||||
return (
|
||||
$columns.some(col => col.name === name && col.visible) ||
|
||||
$sticky?.name === name
|
||||
)
|
||||
return get(columns).some(col => col.name === name && col.visible)
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -25,12 +25,12 @@ const DependencyOrderedStores = [
|
|||
Sort,
|
||||
Filter,
|
||||
Bounds,
|
||||
Scroll,
|
||||
Table,
|
||||
ViewV2,
|
||||
NonPlus,
|
||||
Datasource,
|
||||
Columns,
|
||||
Scroll,
|
||||
Validation,
|
||||
Rows,
|
||||
UI,
|
||||
|
|
|
@ -28,10 +28,12 @@ export const createActions = context => {
|
|||
const {
|
||||
reorder,
|
||||
columns,
|
||||
visibleColumns,
|
||||
columnLookupMap,
|
||||
scrollableColumns,
|
||||
visibleColumnLookupMap,
|
||||
scroll,
|
||||
bounds,
|
||||
stickyColumn,
|
||||
visibleColumns,
|
||||
maxScrollLeft,
|
||||
width,
|
||||
datasource,
|
||||
|
@ -42,26 +44,14 @@ export const createActions = context => {
|
|||
|
||||
// Callback when dragging on a colum header and starting reordering
|
||||
const startReordering = (column, e) => {
|
||||
const $visibleColumns = get(visibleColumns)
|
||||
const $scrollableColumns = get(scrollableColumns)
|
||||
const $bounds = get(bounds)
|
||||
const $stickyColumn = get(stickyColumn)
|
||||
|
||||
// Generate new breakpoints for the current columns
|
||||
let breakpoints = $visibleColumns.map(col => ({
|
||||
x: col.left + col.width,
|
||||
const breakpoints = $scrollableColumns.map(col => ({
|
||||
x: col.__left + col.width,
|
||||
column: col.name,
|
||||
}))
|
||||
if ($stickyColumn) {
|
||||
breakpoints.unshift({
|
||||
x: 0,
|
||||
column: $stickyColumn.name,
|
||||
})
|
||||
} else if (!$visibleColumns[0].primaryDisplay) {
|
||||
breakpoints.unshift({
|
||||
x: 0,
|
||||
column: null,
|
||||
})
|
||||
}
|
||||
|
||||
// Update state
|
||||
reorder.set({
|
||||
|
@ -185,9 +175,9 @@ export const createActions = context => {
|
|||
// Moves a column after another columns.
|
||||
// An undefined target column will move the source to index 0.
|
||||
const moveColumn = async (sourceColumn, targetColumn) => {
|
||||
let $columns = get(columns)
|
||||
let sourceIdx = $columns.findIndex(x => x.name === sourceColumn)
|
||||
let targetIdx = $columns.findIndex(x => x.name === targetColumn)
|
||||
const $columnLookupMap = get(columnLookupMap)
|
||||
let sourceIdx = $columnLookupMap[sourceColumn]
|
||||
let targetIdx = $columnLookupMap[targetColumn]
|
||||
targetIdx++
|
||||
columns.update(state => {
|
||||
const removed = state.splice(sourceIdx, 1)
|
||||
|
@ -209,14 +199,16 @@ export const createActions = context => {
|
|||
// Moves a column one place left (as appears visually)
|
||||
const moveColumnLeft = async column => {
|
||||
const $visibleColumns = get(visibleColumns)
|
||||
const sourceIdx = $visibleColumns.findIndex(x => x.name === column)
|
||||
const $visibleColumnLookupMap = get(visibleColumnLookupMap)
|
||||
const sourceIdx = $visibleColumnLookupMap[column]
|
||||
await moveColumn(column, $visibleColumns[sourceIdx - 2]?.name)
|
||||
}
|
||||
|
||||
// Moves a column one place right (as appears visually)
|
||||
const moveColumnRight = async column => {
|
||||
const $visibleColumns = get(visibleColumns)
|
||||
const sourceIdx = $visibleColumns.findIndex(x => x.name === column)
|
||||
const $visibleColumnLookupMap = get(visibleColumnLookupMap)
|
||||
const sourceIdx = $visibleColumnLookupMap[column]
|
||||
if (sourceIdx === $visibleColumns.length - 1) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ export const createActions = context => {
|
|||
// Set initial store state
|
||||
resize.set({
|
||||
width: column.width,
|
||||
left: column.left,
|
||||
left: column.__left,
|
||||
initialWidth: column.width,
|
||||
initialMouseX: x,
|
||||
column: column.name,
|
||||
|
|
|
@ -24,7 +24,7 @@ export const deriveStores = context => {
|
|||
const {
|
||||
rows,
|
||||
visibleColumns,
|
||||
stickyColumn,
|
||||
displayColumn,
|
||||
rowHeight,
|
||||
width,
|
||||
height,
|
||||
|
@ -32,7 +32,7 @@ export const deriveStores = context => {
|
|||
} = context
|
||||
|
||||
// Memoize store primitives
|
||||
const stickyColumnWidth = derived(stickyColumn, $col => $col?.width || 0, 0)
|
||||
const stickyColumnWidth = derived(displayColumn, $col => $col?.width || 0, 0)
|
||||
|
||||
// Derive vertical limits
|
||||
const contentHeight = derived(
|
||||
|
@ -196,7 +196,7 @@ export const initialise = context => {
|
|||
// Ensure column is not cutoff on right edge
|
||||
else {
|
||||
const $buttonColumnWidth = get(buttonColumnWidth)
|
||||
const rightEdge = column.left + column.width
|
||||
const rightEdge = column.__left + column.width
|
||||
const rightBound =
|
||||
$bounds.width + $scroll.left - FocusedCellMinOffset - $buttonColumnWidth
|
||||
delta = rightEdge - rightBound
|
||||
|
|
|
@ -50,7 +50,6 @@ export const deriveStores = context => {
|
|||
rows,
|
||||
rowLookupMap,
|
||||
rowHeight,
|
||||
stickyColumn,
|
||||
width,
|
||||
selectedRows,
|
||||
cellSelection,
|
||||
|
@ -85,8 +84,8 @@ export const deriveStores = context => {
|
|||
})
|
||||
|
||||
// Derive whether we should use the compact UI, depending on width
|
||||
const compact = derived([stickyColumn, width], ([$stickyColumn, $width]) => {
|
||||
return ($stickyColumn?.width || 0) + $width + GutterWidth < 800
|
||||
const compact = derived(width, $width => {
|
||||
return $width < 600
|
||||
})
|
||||
|
||||
// Derive we have any selected rows or not
|
||||
|
|
Loading…
Reference in New Issue