From b45ba0eba752a62f871dc4c00b392936de4bfc80 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 27 Feb 2023 19:01:23 +0000 Subject: [PATCH] Separate data fetching logic from main sheet and tidy up --- .../src/components/sheet/HeaderRow.svelte | 87 +++++++ .../src/components/sheet/NewRow.svelte | 43 ++++ .../src/components/sheet/Sheet.svelte | 223 ++---------------- .../src/components/sheet/SheetBody.svelte | 3 +- .../src/components/sheet/SheetHeader.svelte | 17 +- .../src/components/sheet/SheetRow.svelte | 8 +- .../src/components/sheet/stores/reorder.js | 2 +- .../src/components/sheet/stores/rows.js | 125 ++++++++++ .../src/components/sheet/stores/viewport.js | 1 - 9 files changed, 285 insertions(+), 224 deletions(-) create mode 100644 packages/frontend-core/src/components/sheet/HeaderRow.svelte create mode 100644 packages/frontend-core/src/components/sheet/NewRow.svelte create mode 100644 packages/frontend-core/src/components/sheet/stores/rows.js diff --git a/packages/frontend-core/src/components/sheet/HeaderRow.svelte b/packages/frontend-core/src/components/sheet/HeaderRow.svelte new file mode 100644 index 0000000000..f41b31715a --- /dev/null +++ b/packages/frontend-core/src/components/sheet/HeaderRow.svelte @@ -0,0 +1,87 @@ + + +
+ + + + + {#each $visibleColumns as column} + reorder.actions.startReordering(column.idx, e)} + width={column.width} + left={column.left} + > + + + {column.name} + + + {/each} +
+ + diff --git a/packages/frontend-core/src/components/sheet/NewRow.svelte b/packages/frontend-core/src/components/sheet/NewRow.svelte new file mode 100644 index 0000000000..800f300b46 --- /dev/null +++ b/packages/frontend-core/src/components/sheet/NewRow.svelte @@ -0,0 +1,43 @@ + + +
+ + + + {#each $visibleColumns as column} + addRow(column)} + width={column.width} + left={column.left} + /> + {/each} +
+ + diff --git a/packages/frontend-core/src/components/sheet/Sheet.svelte b/packages/frontend-core/src/components/sheet/Sheet.svelte index 7b616706cc..01e24b2948 100644 --- a/packages/frontend-core/src/components/sheet/Sheet.svelte +++ b/packages/frontend-core/src/components/sheet/Sheet.svelte @@ -1,16 +1,16 @@
- - -
- - - - - {#each $visibleColumns as column} - reorder.actions.startReordering(column.idx, e)} - width={column.width} - left={column.left} - > - - - {column.name} - - - {/each} -
- - + + + {#each $visibleRows as row (row._id)} - + {/each} - - -
- - - - {#each $visibleColumns as column} - addRow(column)} - width={column.width} - left={column.left} - /> - {/each} -
-
+ +
@@ -289,22 +130,4 @@ .sheet :global(*) { box-sizing: border-box; } - - .row { - display: flex; - position: sticky; - top: 0; - width: inherit; - z-index: 10; - } - .row.new { - position: absolute; - transform: translateY(var(--top)); - } - .row :global(> :last-child) { - border-right-width: 1px; - } - input[type="checkbox"] { - margin: 0; - } diff --git a/packages/frontend-core/src/components/sheet/SheetBody.svelte b/packages/frontend-core/src/components/sheet/SheetBody.svelte index fc5ea694ac..308d17a726 100644 --- a/packages/frontend-core/src/components/sheet/SheetBody.svelte +++ b/packages/frontend-core/src/components/sheet/SheetBody.svelte @@ -2,7 +2,7 @@ import { getContext, onMount } from "svelte" import { Utils } from "../../utils" - const { columns, selectedCellId, rand, cellHeight, rows, bounds, scroll } = + const { columns, selectedCellId, cellHeight, rows, bounds, scroll } = getContext("spreadsheet") const padding = 180 @@ -45,7 +45,6 @@ class="sheet-body" class:horizontally-scrolled={$scroll.left > 0} on:click|self={() => ($selectedCellId = null)} - id={`sheet-${rand}-body`} on:scroll={handleScroll} >
{ - await API.deleteRows({ - tableId, - rows: rowsToDelete, - }) - await spreadsheetAPI.refreshData() + await rows.actions.deleteRows(rowsToDelete) // Refresh state $selectedCellId = null - $hoveredRowId = null $selectedRows = {} } diff --git a/packages/frontend-core/src/components/sheet/SheetRow.svelte b/packages/frontend-core/src/components/sheet/SheetRow.svelte index f73cf1a5c4..602a23c4b1 100644 --- a/packages/frontend-core/src/components/sheet/SheetRow.svelte +++ b/packages/frontend-core/src/components/sheet/SheetRow.svelte @@ -14,14 +14,12 @@ selectedCellId, reorder, selectedRows, - changeCache, - spreadsheetAPI, + rows, visibleColumns, cellHeight, } = getContext("spreadsheet") $: rowSelected = !!$selectedRows[row._id] - $: data = { ...row, ...$changeCache[row._id] } const getCellForField = field => { const type = field.schema.type @@ -71,10 +69,10 @@ > spreadsheetAPI.updateValue(row._id, column, val)} + onChange={val => rows.actions.updateRow(row._id, column, val)} readonly={column.schema.autocolumn} /> diff --git a/packages/frontend-core/src/components/sheet/stores/reorder.js b/packages/frontend-core/src/components/sheet/stores/reorder.js index dd07cd043a..9a50e05476 100644 --- a/packages/frontend-core/src/components/sheet/stores/reorder.js +++ b/packages/frontend-core/src/components/sheet/stores/reorder.js @@ -1,7 +1,7 @@ import { get, writable } from "svelte/store" export const createReorderStores = context => { - const { columns, visibleColumns, rand, scroll, bounds } = context + const { columns, rand, scroll, bounds } = context const reorderInitialState = { columnIdx: null, swapColumnIdx: null, diff --git a/packages/frontend-core/src/components/sheet/stores/rows.js b/packages/frontend-core/src/components/sheet/stores/rows.js new file mode 100644 index 0000000000..4b35f45a7e --- /dev/null +++ b/packages/frontend-core/src/components/sheet/stores/rows.js @@ -0,0 +1,125 @@ +import { writable, derived, get } from "svelte/store" +import { buildLuceneQuery } from "../../../utils/lucene" +import { fetchData } from "../../../fetch/fetchData" + +export const createRowsStore = context => { + const { tableId, filter, API } = context + const rows = writable([]) + const schema = writable({}) + const primaryDisplay = writable(null) + const query = derived(filter, $filter => buildLuceneQuery($filter)) + const fetch = derived(tableId, $tableId => { + return fetchData({ + API, + datasource: { + type: "table", + tableId: $tableId, + }, + options: { + sortColumn: null, + sortOrder: null, + query: get(query), + limit: 100, + paginate: true, + }, + }) + }) + + // Update fetch when query changes + query.subscribe($query => { + get(fetch).update({ + query: $query, + }) + }) + + // Observe each data fetch and extract some data + fetch.subscribe($fetch => { + $fetch.subscribe($$fetch => { + console.log("new fetch") + rows.set($$fetch.rows.map((row, idx) => ({ ...row, __idx: idx }))) + schema.set($$fetch.schema) + primaryDisplay.set($$fetch.definition?.primaryDisplay) + }) + }) + + // Adds a new empty row + const addRow = async () => { + let newRow = await API.saveRow({ tableId: get(tableId) }) + newRow.__idx = get(rows).length + rows.update(state => { + state.push(newRow) + return state + }) + return newRow + } + + // Updates a value of a row + const updateRow = async (rowId, column, value) => { + const $rows = get(rows) + const index = $rows.findIndex(x => x._id === rowId) + const row = $rows[index] + if (index === -1 || row?.[column.name] === value) { + return + } + + // Immediately update state so that the change is reflected + let newRow = { ...row, [column.name]: value } + rows.update(state => { + state[index] = { ...newRow } + return state + }) + + // Save change + delete newRow.__idx + await API.saveRow(newRow) + + // Fetch row from the server again + newRow = await API.fetchRow({ + tableId: get(tableId), + rowId: row._id, + }) + + // Update state again with this row + newRow = { ...newRow, __idx: row.__idx } + rows.update(state => { + state[index] = newRow + return state + }) + + return newRow + } + + // Deletes an array of rows + const deleteRows = async rowsToDelete => { + const deletedIds = rowsToDelete.map(row => row._id) + + // Actually delete rows + rowsToDelete.forEach(row => { + delete row.__idx + }) + await API.deleteRows({ + tableId: get(tableId), + rows: rowsToDelete, + }) + + // Update state + rows.update(state => { + return state + .filter(row => !deletedIds.includes(row._id)) + .map((row, idx) => ({ ...row, __idx: idx })) + }) + } + + return { + rows: { + ...rows, + actions: { + addRow, + updateRow, + deleteRows, + }, + }, + schema, + primaryDisplay, + } +} diff --git a/packages/frontend-core/src/components/sheet/stores/viewport.js b/packages/frontend-core/src/components/sheet/stores/viewport.js index f4801dcfba..934b0e8c1a 100644 --- a/packages/frontend-core/src/components/sheet/stores/viewport.js +++ b/packages/frontend-core/src/components/sheet/stores/viewport.js @@ -1,5 +1,4 @@ import { writable, derived } from "svelte/store" -import { Utils } from "../../../utils" export const createViewportStores = context => { const { cellHeight, columns, rows, scroll, bounds } = context