Refactor grid to split up stores and provide better separation of datasource-specific logic
This commit is contained in:
parent
ab47e49dd9
commit
e3cf0667be
|
@ -61,7 +61,7 @@
|
||||||
allowDeleteRows={!isUsersTable}
|
allowDeleteRows={!isUsersTable}
|
||||||
schemaOverrides={isUsersTable ? userSchemaOverrides : null}
|
schemaOverrides={isUsersTable ? userSchemaOverrides : null}
|
||||||
showAvatars={false}
|
showAvatars={false}
|
||||||
on:updatetable={handleGridTableUpdate}
|
on:updatedatasource={handleGridTableUpdate}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="filter">
|
<svelte:fragment slot="filter">
|
||||||
<GridFilterButton />
|
<GridFilterButton />
|
||||||
|
|
|
@ -2,22 +2,22 @@
|
||||||
import TableFilterButton from "../TableFilterButton.svelte"
|
import TableFilterButton from "../TableFilterButton.svelte"
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
const { columns, tableId, filter, table } = getContext("grid")
|
const { columns, datasource, filter, definition } = getContext("grid")
|
||||||
|
|
||||||
// Wipe filter whenever table ID changes to avoid using stale filters
|
// Wipe filter whenever table ID changes to avoid using stale filters
|
||||||
$: $tableId, filter.set([])
|
$: $datasource, filter.set([])
|
||||||
|
|
||||||
const onFilter = e => {
|
const onFilter = e => {
|
||||||
filter.set(e.detail || [])
|
filter.set(e.detail || [])
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#key $tableId}
|
{#key $datasource}
|
||||||
<TableFilterButton
|
<TableFilterButton
|
||||||
schema={$table?.schema}
|
schema={$definition?.schema}
|
||||||
filters={$filter}
|
filters={$filter}
|
||||||
on:change={onFilter}
|
on:change={onFilter}
|
||||||
disabled={!$columns.length}
|
disabled={!$columns.length}
|
||||||
tableId={$tableId}
|
tableId={$datasource.tableId}
|
||||||
/>
|
/>
|
||||||
{/key}
|
{/key}
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
|
|
||||||
const { rows, datasource, table } = getContext("grid")
|
const { rows, datasource, definition } = getContext("grid")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ImportButton
|
<ImportButton
|
||||||
{disabled}
|
{disabled}
|
||||||
tableId={$datasource.tableId}
|
tableId={$datasource?.tableId}
|
||||||
tableType={$table?.type}
|
tableType={$definition?.type}
|
||||||
on:importrows={rows.actions.refreshData}
|
on:importrows={rows.actions.refreshData}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import ManageAccessButton from "../ManageAccessButton.svelte"
|
import ManageAccessButton from "../ManageAccessButton.svelte"
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
const { tableId } = getContext("grid")
|
const { datasource } = getContext("grid")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ManageAccessButton resourceId={$tableId} />
|
<ManageAccessButton resourceId={$datasource?.tableId} />
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
import ExistingRelationshipButton from "../ExistingRelationshipButton.svelte"
|
import ExistingRelationshipButton from "../ExistingRelationshipButton.svelte"
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
const { table, rows } = getContext("grid")
|
const { definition, rows } = getContext("grid")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $table}
|
{#if $definition}
|
||||||
<ExistingRelationshipButton
|
<ExistingRelationshipButton
|
||||||
table={$table}
|
table={$definition}
|
||||||
on:updatecolumns={() => rows.actions.refreshData()}
|
on:updatecolumns={() => rows.actions.refreshData()}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import CreateEditColumn from "components/backend/DataTable/modals/CreateEditColumn.svelte"
|
import CreateEditColumn from "components/backend/DataTable/modals/CreateEditColumn.svelte"
|
||||||
|
|
||||||
const { rows } = getContext("grid")
|
const { datasource } = getContext("grid")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<CreateEditColumn on:updatecolumns={rows.actions.refreshDatasourceDefinition} />
|
<CreateEditColumn on:updatecolumns={datasource.actions.refreshDefinition} />
|
||||||
|
|
|
@ -8,8 +8,14 @@
|
||||||
SmallRowHeight,
|
SmallRowHeight,
|
||||||
} from "../lib/constants"
|
} from "../lib/constants"
|
||||||
|
|
||||||
const { stickyColumn, columns, rowHeight, table, fixedRowHeight } =
|
const {
|
||||||
getContext("grid")
|
stickyColumn,
|
||||||
|
columns,
|
||||||
|
rowHeight,
|
||||||
|
definition,
|
||||||
|
fixedRowHeight,
|
||||||
|
datasource,
|
||||||
|
} = getContext("grid")
|
||||||
|
|
||||||
// Some constants for column width options
|
// Some constants for column width options
|
||||||
const smallColSize = 120
|
const smallColSize = 120
|
||||||
|
@ -60,8 +66,8 @@
|
||||||
]
|
]
|
||||||
|
|
||||||
const changeRowHeight = height => {
|
const changeRowHeight = height => {
|
||||||
columns.actions.saveTable({
|
datasource.actions.saveDefinition({
|
||||||
...$table,
|
...$definition,
|
||||||
rowHeight: height,
|
rowHeight: height,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export { default as Grid } from "./layout/Grid.svelte"
|
export { default as Grid } from "./layout/Grid.svelte"
|
||||||
|
export { DatasourceType } from "./lib/constants"
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
export const DatasourceType = {
|
||||||
|
Table: "table",
|
||||||
|
ViewV2: "viewV2",
|
||||||
|
}
|
||||||
export const Padding = 246
|
export const Padding = 246
|
||||||
export const MaxCellRenderHeight = 222
|
export const MaxCellRenderHeight = 222
|
||||||
export const ScrollBarSize = 8
|
export const ScrollBarSize = 8
|
||||||
|
|
|
@ -69,8 +69,7 @@ export const deriveStores = context => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createActions = context => {
|
export const createActions = context => {
|
||||||
const { table, columns, stickyColumn, API, dispatch, config, datasource } =
|
const { columns, stickyColumn, config, datasource, definition } = context
|
||||||
context
|
|
||||||
|
|
||||||
// Checks if we have a certain column by name
|
// Checks if we have a certain column by name
|
||||||
const hasColumn = column => {
|
const hasColumn = column => {
|
||||||
|
@ -79,13 +78,13 @@ export const createActions = context => {
|
||||||
return $columns.some(col => col.name === column) || $sticky?.name === column
|
return $columns.some(col => col.name === column) || $sticky?.name === column
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates the tables primary display column
|
// Updates the datasources primary display column
|
||||||
const changePrimaryDisplay = async column => {
|
const changePrimaryDisplay = async column => {
|
||||||
if (!get(config).canEditPrimaryDisplay) {
|
if (!get(config).canEditPrimaryDisplay) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return await saveTable({
|
return await datasource.actions.saveDefinition({
|
||||||
...get(table),
|
...get(definition),
|
||||||
primaryDisplay: column,
|
primaryDisplay: column,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -107,14 +106,14 @@ export const createActions = context => {
|
||||||
await saveChanges()
|
await saveChanges()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Persists column changes by saving metadata against table schema
|
// Persists column changes by saving metadata against datasource schema
|
||||||
const saveChanges = async () => {
|
const saveChanges = async () => {
|
||||||
const $columns = get(columns)
|
const $columns = get(columns)
|
||||||
const $table = get(table)
|
const $definition = get(definition)
|
||||||
const $stickyColumn = get(stickyColumn)
|
const $stickyColumn = get(stickyColumn)
|
||||||
const newSchema = cloneDeep($table.schema)
|
const newSchema = cloneDeep($definition.schema)
|
||||||
|
|
||||||
// Build new updated table schema
|
// Build new updated datasource schema
|
||||||
Object.keys(newSchema).forEach(column => {
|
Object.keys(newSchema).forEach(column => {
|
||||||
// Respect order specified by columns
|
// Respect order specified by columns
|
||||||
const index = $columns.findIndex(x => x.name === column)
|
const index = $columns.findIndex(x => x.name === column)
|
||||||
|
@ -134,28 +133,10 @@ export const createActions = context => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await saveTable({ ...$table, schema: newSchema })
|
await datasource.actions.saveDefinition({
|
||||||
}
|
...$definition,
|
||||||
|
schema: newSchema,
|
||||||
const saveTable = async newTable => {
|
})
|
||||||
const $config = get(config)
|
|
||||||
const $datasource = get(datasource)
|
|
||||||
|
|
||||||
// Update local state
|
|
||||||
table.set(newTable)
|
|
||||||
|
|
||||||
// Update server
|
|
||||||
if ($config.canSaveSchema) {
|
|
||||||
if ($datasource.type === "table") {
|
|
||||||
await API.saveTable(newTable)
|
|
||||||
} else if ($datasource.type === "viewV2") {
|
|
||||||
await API.viewV2.update({ ...newTable })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Broadcast change to external state can be updated, as this change
|
|
||||||
// will not be received by the builder websocket because we caused it ourselves
|
|
||||||
dispatch("updatetable", newTable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -164,7 +145,6 @@ export const createActions = context => {
|
||||||
actions: {
|
actions: {
|
||||||
hasColumn,
|
hasColumn,
|
||||||
saveChanges,
|
saveChanges,
|
||||||
saveTable,
|
|
||||||
changePrimaryDisplay,
|
changePrimaryDisplay,
|
||||||
changeAllColumnWidths,
|
changeAllColumnWidths,
|
||||||
},
|
},
|
||||||
|
@ -173,51 +153,7 @@ export const createActions = context => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialise = context => {
|
export const initialise = context => {
|
||||||
const { table, columns, stickyColumn, schemaOverrides, columnWhitelist } =
|
const { definition, columns, stickyColumn, schema } = context
|
||||||
context
|
|
||||||
|
|
||||||
const schema = derived(
|
|
||||||
[table, schemaOverrides, columnWhitelist],
|
|
||||||
([$table, $schemaOverrides, $columnWhitelist]) => {
|
|
||||||
if (!$table?.schema) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
let newSchema = { ...$table?.schema }
|
|
||||||
|
|
||||||
// Edge case to temporarily allow deletion of duplicated user
|
|
||||||
// fields that were saved with the "disabled" flag set.
|
|
||||||
// By overriding the saved schema we ensure only overrides can
|
|
||||||
// set the disabled flag.
|
|
||||||
// TODO: remove in future
|
|
||||||
Object.keys(newSchema).forEach(field => {
|
|
||||||
newSchema[field] = {
|
|
||||||
...newSchema[field],
|
|
||||||
disabled: false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Apply schema overrides
|
|
||||||
Object.keys($schemaOverrides || {}).forEach(field => {
|
|
||||||
if (newSchema[field]) {
|
|
||||||
newSchema[field] = {
|
|
||||||
...newSchema[field],
|
|
||||||
...$schemaOverrides[field],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Apply whitelist if specified
|
|
||||||
if ($columnWhitelist?.length) {
|
|
||||||
Object.keys(newSchema).forEach(key => {
|
|
||||||
if (!$columnWhitelist.includes(key)) {
|
|
||||||
delete newSchema[key]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return newSchema
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Merge new schema fields with existing schema in order to preserve widths
|
// Merge new schema fields with existing schema in order to preserve widths
|
||||||
schema.subscribe($schema => {
|
schema.subscribe($schema => {
|
||||||
|
@ -226,12 +162,12 @@ export const initialise = context => {
|
||||||
stickyColumn.set(null)
|
stickyColumn.set(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const $table = get(table)
|
const $definition = get(definition)
|
||||||
|
|
||||||
// Find primary display
|
// Find primary display
|
||||||
let primaryDisplay
|
let primaryDisplay
|
||||||
if ($table.primaryDisplay && $schema[$table.primaryDisplay]) {
|
if ($definition.primaryDisplay && $schema[$definition.primaryDisplay]) {
|
||||||
primaryDisplay = $table.primaryDisplay
|
primaryDisplay = $definition.primaryDisplay
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get field list
|
// Get field list
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { derivedMemo } from "../../../utils"
|
import { derivedMemo } from "../../../utils"
|
||||||
import { derived } from "svelte/store"
|
import { derived } from "svelte/store"
|
||||||
|
import { DatasourceType } from "../lib/constants"
|
||||||
|
|
||||||
export const deriveStores = context => {
|
export const deriveStores = context => {
|
||||||
const { props, hasNonAutoColumn } = context
|
const { props, hasNonAutoColumn } = context
|
||||||
|
@ -28,8 +29,7 @@ export const deriveStores = context => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable some features if we're editing a view
|
// Disable some features if we're editing a view
|
||||||
if ($props.datasource?.type === "viewV2") {
|
if ($props.datasource?.type === DatasourceType.ViewV2) {
|
||||||
config.canEditPrimaryDisplay = false
|
|
||||||
config.canEditColumns = false
|
config.canEditColumns = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { derived, get, writable } from "svelte/store"
|
||||||
|
|
||||||
|
export const createStores = () => {
|
||||||
|
const definition = writable(null)
|
||||||
|
|
||||||
|
return {
|
||||||
|
definition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deriveStores = context => {
|
||||||
|
const { definition, schemaOverrides, columnWhitelist } = context
|
||||||
|
|
||||||
|
const schema = derived(
|
||||||
|
[definition, schemaOverrides, columnWhitelist],
|
||||||
|
([$definition, $schemaOverrides, $columnWhitelist]) => {
|
||||||
|
if (!$definition?.schema) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
let newSchema = { ...$definition?.schema }
|
||||||
|
|
||||||
|
// Edge case to temporarily allow deletion of duplicated user
|
||||||
|
// fields that were saved with the "disabled" flag set.
|
||||||
|
// By overriding the saved schema we ensure only overrides can
|
||||||
|
// set the disabled flag.
|
||||||
|
// TODO: remove in future
|
||||||
|
Object.keys(newSchema).forEach(field => {
|
||||||
|
newSchema[field] = {
|
||||||
|
...newSchema[field],
|
||||||
|
disabled: false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Apply schema overrides
|
||||||
|
Object.keys($schemaOverrides || {}).forEach(field => {
|
||||||
|
if (newSchema[field]) {
|
||||||
|
newSchema[field] = {
|
||||||
|
...newSchema[field],
|
||||||
|
...$schemaOverrides[field],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Apply whitelist if specified
|
||||||
|
if ($columnWhitelist?.length) {
|
||||||
|
Object.keys(newSchema).forEach(key => {
|
||||||
|
if (!$columnWhitelist.includes(key)) {
|
||||||
|
delete newSchema[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return newSchema
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
schema,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createActions = context => {
|
||||||
|
const { datasource, definition, API, config, dispatch } = context
|
||||||
|
|
||||||
|
// Refreshes the datasource definition
|
||||||
|
const refreshDefinition = async () => {
|
||||||
|
const $datasource = get(datasource)
|
||||||
|
if ($datasource.type === "table") {
|
||||||
|
definition.set(await API.fetchTableDefinition($datasource.tableId))
|
||||||
|
} else if ($datasource.type === "viewV2") {
|
||||||
|
// const definition = await API.viewsV2.(get(tableId))
|
||||||
|
// table.set(definition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Saves the datasource definition
|
||||||
|
const saveDefinition = async newDefinition => {
|
||||||
|
const $config = get(config)
|
||||||
|
const $datasource = get(datasource)
|
||||||
|
|
||||||
|
// Update local state
|
||||||
|
definition.set(newDefinition)
|
||||||
|
|
||||||
|
// Update server
|
||||||
|
if ($config.canSaveSchema) {
|
||||||
|
if ($datasource.type === "table") {
|
||||||
|
await API.saveTable(newDefinition)
|
||||||
|
} else if ($datasource.type === "viewV2") {
|
||||||
|
await API.viewV2.update({ ...newDefinition })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast change to external state can be updated, as this change
|
||||||
|
// will not be received by the builder websocket because we caused it ourselves
|
||||||
|
dispatch("updatedefinition", newDefinition)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
datasource: {
|
||||||
|
...datasource,
|
||||||
|
actions: {
|
||||||
|
refreshDefinition,
|
||||||
|
saveDefinition,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,13 +15,18 @@ import * as Config from "./config"
|
||||||
import * as Sort from "./sort"
|
import * as Sort from "./sort"
|
||||||
import * as Filter from "./filter"
|
import * as Filter from "./filter"
|
||||||
import * as Notifications from "./notifications"
|
import * as Notifications from "./notifications"
|
||||||
|
import * as Table from "./table"
|
||||||
|
import * as ViewV2 from "./viewV2"
|
||||||
|
import * as Datasource from "./datsource"
|
||||||
|
|
||||||
const DependencyOrderedStores = [
|
const DependencyOrderedStores = [
|
||||||
|
// Common stores
|
||||||
Notifications,
|
Notifications,
|
||||||
Sort,
|
Sort,
|
||||||
Filter,
|
Filter,
|
||||||
Bounds,
|
Bounds,
|
||||||
Scroll,
|
Scroll,
|
||||||
|
Datasource,
|
||||||
Columns,
|
Columns,
|
||||||
Rows,
|
Rows,
|
||||||
UI,
|
UI,
|
||||||
|
@ -34,6 +39,10 @@ const DependencyOrderedStores = [
|
||||||
Pagination,
|
Pagination,
|
||||||
Clipboard,
|
Clipboard,
|
||||||
Config,
|
Config,
|
||||||
|
|
||||||
|
// Datasource specific stores
|
||||||
|
Table,
|
||||||
|
ViewV2,
|
||||||
]
|
]
|
||||||
|
|
||||||
export const attachStores = context => {
|
export const attachStores = context => {
|
||||||
|
|
|
@ -7,13 +7,13 @@ const SuppressErrors = true
|
||||||
|
|
||||||
export const createStores = () => {
|
export const createStores = () => {
|
||||||
const rows = writable([])
|
const rows = writable([])
|
||||||
const table = writable(null)
|
|
||||||
const loading = writable(false)
|
const loading = writable(false)
|
||||||
const loaded = writable(false)
|
const loaded = writable(false)
|
||||||
const rowChangeCache = writable({})
|
const rowChangeCache = writable({})
|
||||||
const inProgressChanges = writable({})
|
const inProgressChanges = writable({})
|
||||||
const hasNextPage = writable(false)
|
const hasNextPage = writable(false)
|
||||||
const error = writable(null)
|
const error = writable(null)
|
||||||
|
const fetch = writable(null)
|
||||||
|
|
||||||
// Generate a lookup map to quick find a row by ID
|
// Generate a lookup map to quick find a row by ID
|
||||||
const rowLookupMap = derived(rows, $rows => {
|
const rowLookupMap = derived(rows, $rows => {
|
||||||
|
@ -51,8 +51,8 @@ export const createStores = () => {
|
||||||
...rows,
|
...rows,
|
||||||
subscribe: enrichedRows.subscribe,
|
subscribe: enrichedRows.subscribe,
|
||||||
},
|
},
|
||||||
|
fetch,
|
||||||
rowLookupMap,
|
rowLookupMap,
|
||||||
table,
|
|
||||||
loaded,
|
loaded,
|
||||||
loading,
|
loading,
|
||||||
rowChangeCache,
|
rowChangeCache,
|
||||||
|
@ -66,7 +66,7 @@ export const createActions = context => {
|
||||||
const {
|
const {
|
||||||
rows,
|
rows,
|
||||||
rowLookupMap,
|
rowLookupMap,
|
||||||
table,
|
definition,
|
||||||
filter,
|
filter,
|
||||||
loading,
|
loading,
|
||||||
sort,
|
sort,
|
||||||
|
@ -82,14 +82,14 @@ export const createActions = context => {
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
error,
|
error,
|
||||||
notifications,
|
notifications,
|
||||||
|
fetch,
|
||||||
} = context
|
} = context
|
||||||
const instanceLoaded = writable(false)
|
const instanceLoaded = writable(false)
|
||||||
const fetch = writable(null)
|
|
||||||
|
|
||||||
// Local cache of row IDs to speed up checking if a row exists
|
// Local cache of row IDs to speed up checking if a row exists
|
||||||
let rowCacheMap = {}
|
let rowCacheMap = {}
|
||||||
|
|
||||||
// Reset everything when table ID changes
|
// Reset everything when datasource changes
|
||||||
let unsubscribe = null
|
let unsubscribe = null
|
||||||
let lastResetKey = null
|
let lastResetKey = null
|
||||||
datasource.subscribe(async $datasource => {
|
datasource.subscribe(async $datasource => {
|
||||||
|
@ -100,11 +100,11 @@ export const createActions = context => {
|
||||||
loading.set(true)
|
loading.set(true)
|
||||||
|
|
||||||
// Abandon if we don't have a valid datasource
|
// Abandon if we don't have a valid datasource
|
||||||
if (!$datasource?.tableId) {
|
if (!$datasource) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tick to allow other reactive logic to update stores when table ID changes
|
// Tick to allow other reactive logic to update stores when datasource changes
|
||||||
// before proceeding. This allows us to wipe filters etc if needed.
|
// before proceeding. This allows us to wipe filters etc if needed.
|
||||||
await tick()
|
await tick()
|
||||||
const $filter = get(filter)
|
const $filter = get(filter)
|
||||||
|
@ -142,7 +142,7 @@ export const createActions = context => {
|
||||||
const previousResetKey = lastResetKey
|
const previousResetKey = lastResetKey
|
||||||
lastResetKey = $fetch.resetKey
|
lastResetKey = $fetch.resetKey
|
||||||
|
|
||||||
// If resetting rows due to a table change, wipe data and wait for
|
// If resetting rows due to a datasource change, wipe data and wait for
|
||||||
// derived stores to compute. This prevents stale data being passed
|
// derived stores to compute. This prevents stale data being passed
|
||||||
// to cells when we save the new schema.
|
// to cells when we save the new schema.
|
||||||
if (!$instanceLoaded && previousResetKey) {
|
if (!$instanceLoaded && previousResetKey) {
|
||||||
|
@ -152,16 +152,17 @@ export const createActions = context => {
|
||||||
|
|
||||||
// Reset state properties when dataset changes
|
// Reset state properties when dataset changes
|
||||||
if (!$instanceLoaded || resetRows) {
|
if (!$instanceLoaded || resetRows) {
|
||||||
table.set($fetch.definition)
|
definition.set($fetch.definition)
|
||||||
sort.set({
|
|
||||||
column: $fetch.sortColumn,
|
// sort.set({
|
||||||
order: $fetch.sortOrder,
|
// column: $fetch.sortColumn,
|
||||||
})
|
// order: $fetch.sortOrder,
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset scroll state when data changes
|
// Reset scroll state when data changes
|
||||||
if (!$instanceLoaded) {
|
if (!$instanceLoaded) {
|
||||||
// Reset both top and left for a new table ID
|
// Reset both top and left for a new datasource ID
|
||||||
instanceLoaded.set(true)
|
instanceLoaded.set(true)
|
||||||
scroll.set({ top: 0, left: 0 })
|
scroll.set({ top: 0, left: 0 })
|
||||||
} else if (resetRows) {
|
} else if (resetRows) {
|
||||||
|
@ -169,8 +170,6 @@ export const createActions = context => {
|
||||||
scroll.update(state => ({ ...state, top: 0 }))
|
scroll.update(state => ({ ...state, top: 0 }))
|
||||||
}
|
}
|
||||||
|
|
||||||
// For views we always update the filter to match the definition
|
|
||||||
|
|
||||||
// Process new rows
|
// Process new rows
|
||||||
handleNewRows($fetch.rows, resetRows)
|
handleNewRows($fetch.rows, resetRows)
|
||||||
|
|
||||||
|
@ -182,23 +181,6 @@ export const createActions = context => {
|
||||||
fetch.set(newFetch)
|
fetch.set(newFetch)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update fetch when filter or sort config changes
|
|
||||||
filter.subscribe($filter => {
|
|
||||||
if (get(datasource)?.type === "table") {
|
|
||||||
get(fetch)?.update({
|
|
||||||
filter: $filter,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
sort.subscribe($sort => {
|
|
||||||
if (get(datasource)?.type === "table") {
|
|
||||||
get(fetch)?.update({
|
|
||||||
sortOrder: $sort.order,
|
|
||||||
sortColumn: $sort.column,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Gets a row by ID
|
// Gets a row by ID
|
||||||
const getRow = id => {
|
const getRow = id => {
|
||||||
const index = get(rowLookupMap)[id]
|
const index = get(rowLookupMap)[id]
|
||||||
|
@ -506,17 +488,6 @@ export const createActions = context => {
|
||||||
get(fetch)?.nextPage()
|
get(fetch)?.nextPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refreshes the schema of the data fetch subscription
|
|
||||||
const refreshDatasourceDefinition = async () => {
|
|
||||||
const $datasource = get(datasource)
|
|
||||||
if ($datasource.type === "table") {
|
|
||||||
table.set(await API.fetchTableDefinition($datasource.tableId))
|
|
||||||
} else if ($datasource.type === "viewV2") {
|
|
||||||
// const definition = await API.viewsV2.(get(tableId))
|
|
||||||
// table.set(definition)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if we have a row with a certain ID
|
// Checks if we have a row with a certain ID
|
||||||
const hasRow = id => {
|
const hasRow = id => {
|
||||||
if (id === NewRowID) {
|
if (id === NewRowID) {
|
||||||
|
@ -550,21 +521,7 @@ export const createActions = context => {
|
||||||
refreshRow,
|
refreshRow,
|
||||||
replaceRow,
|
replaceRow,
|
||||||
refreshData,
|
refreshData,
|
||||||
refreshDatasourceDefinition,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialise = context => {
|
|
||||||
const { table, filter, datasource } = context
|
|
||||||
|
|
||||||
// For views, always keep the UI for filter and sorting up to date with the
|
|
||||||
// latest view definition
|
|
||||||
table.subscribe($definition => {
|
|
||||||
if (!$definition || get(datasource)?.type !== "viewV2") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
filter.set($definition.query)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ export const createStores = context => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialise = context => {
|
export const initialise = context => {
|
||||||
const { sort, initialSortColumn, initialSortOrder } = context
|
const { sort, initialSortColumn, initialSortOrder, table, datasource } =
|
||||||
|
context
|
||||||
|
|
||||||
// Reset sort when initial sort props change
|
// Reset sort when initial sort props change
|
||||||
initialSortColumn.subscribe(newSortColumn => {
|
initialSortColumn.subscribe(newSortColumn => {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { get } from "svelte/store"
|
||||||
|
|
||||||
|
export const initialise = context => {
|
||||||
|
const { datasource, fetch, filter, sort } = context
|
||||||
|
|
||||||
|
// Update fetch when filter changes
|
||||||
|
filter.subscribe($filter => {
|
||||||
|
if (get(datasource)?.type === "table") {
|
||||||
|
get(fetch)?.update({
|
||||||
|
filter: $filter,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update fetch when sorting changes
|
||||||
|
sort.subscribe($sort => {
|
||||||
|
if (get(datasource)?.type === "table") {
|
||||||
|
get(fetch)?.update({
|
||||||
|
sortOrder: $sort.order,
|
||||||
|
sortColumn: $sort.column,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -131,7 +131,7 @@ export const initialise = context => {
|
||||||
focusedCellId,
|
focusedCellId,
|
||||||
selectedRows,
|
selectedRows,
|
||||||
hoveredRowId,
|
hoveredRowId,
|
||||||
table,
|
definition,
|
||||||
rowHeight,
|
rowHeight,
|
||||||
fixedRowHeight,
|
fixedRowHeight,
|
||||||
} = context
|
} = context
|
||||||
|
@ -187,9 +187,9 @@ export const initialise = context => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Pull row height from table as long as we don't have a fixed height
|
// Pull row height from table as long as we don't have a fixed height
|
||||||
table.subscribe($table => {
|
definition.subscribe($definition => {
|
||||||
if (!get(fixedRowHeight)) {
|
if (!get(fixedRowHeight)) {
|
||||||
rowHeight.set($table?.rowHeight || DefaultRowHeight)
|
rowHeight.set($definition?.rowHeight || DefaultRowHeight)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ export const initialise = context => {
|
||||||
if (height) {
|
if (height) {
|
||||||
rowHeight.set(height)
|
rowHeight.set(height)
|
||||||
} else {
|
} else {
|
||||||
rowHeight.set(get(table)?.rowHeight || DefaultRowHeight)
|
rowHeight.set(get(definition)?.rowHeight || DefaultRowHeight)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { get } from "svelte/store"
|
||||||
|
|
||||||
|
export const initialise = context => {
|
||||||
|
const { definition, datasource, sort, rows } = context
|
||||||
|
|
||||||
|
// For views, keep sort state in line with the view definition
|
||||||
|
definition.subscribe($definition => {
|
||||||
|
if (!$definition || get(datasource)?.type !== "viewV2") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const $sort = get(sort)
|
||||||
|
if (
|
||||||
|
$definition.sort?.field !== $sort?.column ||
|
||||||
|
$definition.sort?.order !== $sort?.order
|
||||||
|
) {
|
||||||
|
sort.set({
|
||||||
|
column: $definition.sort?.field,
|
||||||
|
order: $definition.sort?.order,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// When sorting changes, ensure view definition is kept up to date
|
||||||
|
sort.subscribe(async $sort => {
|
||||||
|
const $view = get(definition)
|
||||||
|
if (!$view || get(datasource)?.type !== "viewV2") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
$sort?.column !== $view.sort?.field ||
|
||||||
|
$sort?.order !== $view.sort?.order
|
||||||
|
) {
|
||||||
|
await datasource.actions.saveDefinition({
|
||||||
|
...$view,
|
||||||
|
sort: {
|
||||||
|
field: $sort.column,
|
||||||
|
order: $sort.order,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await rows.actions.refreshData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -116,8 +116,16 @@ export default class DataFetch {
|
||||||
async getInitialData() {
|
async getInitialData() {
|
||||||
const { datasource, filter, paginate } = this.options
|
const { datasource, filter, paginate } = this.options
|
||||||
|
|
||||||
// Fetch datasource definition and determine feature flags
|
// Fetch datasource definition and extract filter and sort if configured
|
||||||
const definition = await this.getDefinition(datasource)
|
const definition = await this.getDefinition(datasource)
|
||||||
|
if (definition?.sort?.field) {
|
||||||
|
this.options.sortColumn = definition.sort.field
|
||||||
|
}
|
||||||
|
if (definition?.sort?.order) {
|
||||||
|
this.options.sortOrder = definition.sort.order
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine feature flags
|
||||||
const features = this.determineFeatureFlags(definition)
|
const features = this.determineFeatureFlags(definition)
|
||||||
this.features = {
|
this.features = {
|
||||||
supportsSearch: !!features?.supportsSearch,
|
supportsSearch: !!features?.supportsSearch,
|
||||||
|
|
Loading…
Reference in New Issue