Refactor to use IDs and support changing text values inline

This commit is contained in:
Andrew Kingston 2022-11-24 16:41:53 +00:00
parent 1c3b6e0cec
commit b19a2a3d3a
2 changed files with 61 additions and 17 deletions

View File

@ -21,6 +21,7 @@
let selectedCell let selectedCell
let selectedRows = {} let selectedRows = {}
let horizontallyScrolled = false let horizontallyScrolled = false
let changeCache = {}
$: query = LuceneUtils.buildLuceneQuery(filter) $: query = LuceneUtils.buildLuceneQuery(filter)
$: fetch = createFetch(table) $: fetch = createFetch(table)
@ -89,8 +90,8 @@
return "Text" return "Text"
} }
const selectRow = idx => { const selectRow = id => {
selectedRows[idx] = !selectedRows[idx] selectedRows[id] = !selectedRows[id]
} }
const selectAll = () => { const selectAll = () => {
@ -98,11 +99,27 @@
if (allSelected) { if (allSelected) {
selectedRows = {} selectedRows = {}
} else { } else {
for (let i = 0; i < rowCount; i++) { $fetch.rows.forEach(row => {
selectedRows[i] = true selectedRows[row._id] = true
} })
} }
} }
const handleChange = async (rowId, field, value) => {
selectedCell = null
let row = $fetch.rows.find(x => x._id === rowId)
if (!row) {
return
}
const newRow = {
...row,
[field]: value,
}
changeCache[rowId] = { [field]: value }
await API.saveRow(newRow)
await fetch.refresh()
delete changeCache[rowId]
}
</script> </script>
<div use:styleable={$component.styles}> <div use:styleable={$component.styles}>
@ -147,16 +164,17 @@
{/each} {/each}
<!-- All real rows --> <!-- All real rows -->
{#each $fetch.rows as row, rowIdx} {#each $fetch.rows as row, rowIdx (row._id)}
{@const rowSelected = !!selectedRows[rowIdx]} {@const rowSelected = !!selectedRows[row._id]}
{@const rowHovered = hoveredRow === rowIdx} {@const rowHovered = hoveredRow === row._id}
{@const data = { ...row, ...changeCache[row._id] }}
<div <div
class="cell label" class="cell label"
class:row-selected={rowSelected} class:row-selected={rowSelected}
class:hovered={rowHovered} class:hovered={rowHovered}
on:focus on:focus
on:mouseover={() => (hoveredRow = rowIdx)} on:mouseover={() => (hoveredRow = row._id)}
on:click={() => selectRow(rowIdx)} on:click={() => selectRow(row._id)}
> >
{#if rowSelected || rowHovered} {#if rowSelected || rowHovered}
<input type="checkbox" checked={rowSelected} /> <input type="checkbox" checked={rowSelected} />
@ -167,7 +185,7 @@
{/if} {/if}
</div> </div>
{#each fields as field, fieldIdx} {#each fields as field, fieldIdx}
{@const cellIdx = rowIdx * fields.length + fieldIdx} {@const cellIdx = `${row._id}-${field}`}
<div <div
class="cell" class="cell"
class:row-selected={rowSelected} class:row-selected={rowSelected}
@ -176,14 +194,15 @@
class:selected={selectedCell === cellIdx} class:selected={selectedCell === cellIdx}
class:shadow={horizontallyScrolled} class:shadow={horizontallyScrolled}
on:focus on:focus
on:mouseover={() => (hoveredRow = rowIdx)} on:mouseover={() => (hoveredRow = row._id)}
on:click={() => (selectedCell = cellIdx)} on:click={() => (selectedCell = cellIdx)}
> >
<svelte:component <svelte:component
this={getCellForField(field)} this={getCellForField(field)}
value={row[field]} value={data[field]}
schema={schema[field]} schema={schema[field]}
selected={selectedCell === cellIdx} selected={selectedCell === cellIdx}
onChange={val => handleChange(row._id, field, val)}
/> />
</div> </div>
{/each} {/each}
@ -292,7 +311,7 @@
z-index: 2; z-index: 2;
} }
.cell.row-selected { .cell.row-selected {
background-color: rgba(20, 122, 243, 0.05); background-color: rgb(224, 242, 255);
} }
.header { .header {

View File

@ -1,10 +1,20 @@
<script> <script>
export let value export let value
export let selected = false
export let onChange
const handleChange = e => {
onChange(e.target.value)
}
</script> </script>
<div class="text-cell"> {#if selected}
{value || ""} <input type="text" value={value || ""} on:change={handleChange} />
</div> {:else}
<div class="text-cell">
{value || ""}
</div>
{/if}
<style> <style>
.text-cell { .text-cell {
@ -13,4 +23,19 @@
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
input {
border: none;
padding: 0;
margin: 0 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background: none;
font-size: 14px;
font-family: var(--font-sans);
color: inherit;
}
input:focus {
outline: none;
}
</style> </style>