Invalidate related tables automatically via client library and fix issue with data source invalidation from modals

This commit is contained in:
Andrew Kingston 2021-10-26 19:12:55 +01:00
parent 54aad2ff1e
commit 262b238388
3 changed files with 48 additions and 35 deletions

View File

@ -20,7 +20,7 @@ export const executeQuery = async ({ queryId, parameters }) => {
notificationStore.actions.error("An error has occurred") notificationStore.actions.error("An error has occurred")
} else if (!query.readable) { } else if (!query.readable) {
notificationStore.actions.success("Query executed successfully") notificationStore.actions.success("Query executed successfully")
dataSourceStore.actions.invalidateDataSource(query.datasourceId) await dataSourceStore.actions.invalidateDataSource(query.datasourceId)
} }
return res return res
} }

View File

@ -31,7 +31,7 @@ export const saveRow = async row => {
: notificationStore.actions.success("Row saved") : notificationStore.actions.success("Row saved")
// Refresh related datasources // Refresh related datasources
dataSourceStore.actions.invalidateDataSource(row.tableId) await dataSourceStore.actions.invalidateDataSource(row.tableId)
return res return res
} }
@ -52,7 +52,7 @@ export const updateRow = async row => {
: notificationStore.actions.success("Row updated") : notificationStore.actions.success("Row updated")
// Refresh related datasources // Refresh related datasources
dataSourceStore.actions.invalidateDataSource(row.tableId) await dataSourceStore.actions.invalidateDataSource(row.tableId)
return res return res
} }
@ -76,7 +76,7 @@ export const deleteRow = async ({ tableId, rowId, revId }) => {
: notificationStore.actions.success("Row deleted") : notificationStore.actions.success("Row deleted")
// Refresh related datasources // Refresh related datasources
dataSourceStore.actions.invalidateDataSource(tableId) await dataSourceStore.actions.invalidateDataSource(tableId)
return res return res
} }
@ -99,7 +99,7 @@ export const deleteRows = async ({ tableId, rows }) => {
: notificationStore.actions.success(`${rows.length} row(s) deleted`) : notificationStore.actions.success(`${rows.length} row(s) deleted`)
// Refresh related datasources // Refresh related datasources
dataSourceStore.actions.invalidateDataSource(tableId) await dataSourceStore.actions.invalidateDataSource(tableId)
return res return res
} }

View File

@ -1,4 +1,5 @@
import { writable, get } from "svelte/store" import { writable, get } from "svelte/store"
import { fetchTableDefinition } from "../api"
export const createDataSourceStore = () => { export const createDataSourceStore = () => {
const store = writable([]) const store = writable([])
@ -9,43 +10,32 @@ export const createDataSourceStore = () => {
return return
} }
// Create a list of all relevant dataSource IDs which would require that // Extract the relevant datasource ID for this datasource
// this dataSource is refreshed let dataSourceId = null
let dataSourceIds = []
// Extract table ID // Extract table ID
if (dataSource.type === "table" || dataSource.type === "view") { if (dataSource.type === "table" || dataSource.type === "view") {
if (dataSource.tableId) { dataSourceId = dataSource.tableId
dataSourceIds.push(dataSource.tableId)
}
} }
// Extract both table IDs from both sides of the relationship // Only one side of the relationship is required as a trigger, as it will
// automatically invalidate related table IDs
else if (dataSource.type === "link") { else if (dataSource.type === "link") {
if (dataSource.rowTableId) { dataSourceId = dataSource.tableId || dataSource.rowTableId
dataSourceIds.push(dataSource.rowTableId)
}
if (dataSource.tableId) {
dataSourceIds.push(dataSource.tableId)
}
} }
// Extract the dataSource ID (not the query ID) for queries // Extract the dataSource ID (not the query ID) for queries
else if (dataSource.type === "query") { else if (dataSource.type === "query") {
if (dataSource.dataSourceId) { dataSourceId = dataSource.dataSourceId
dataSourceIds.push(dataSource.dataSourceId)
}
} }
// Store configs for each relevant dataSource ID // Store configs for each relevant dataSource ID
if (dataSourceIds.length) { if (dataSourceId) {
store.update(state => { store.update(state => {
dataSourceIds.forEach(id => { state.push({
state.push({ dataSourceId,
dataSourceId: id, instanceId,
instanceId, refresh,
refresh,
})
}) })
return state return state
}) })
@ -62,13 +52,10 @@ export const createDataSourceStore = () => {
// Invalidates a specific dataSource ID by refreshing all instances // Invalidates a specific dataSource ID by refreshing all instances
// which depend on data from that dataSource // which depend on data from that dataSource
const invalidateDataSource = dataSourceId => { const invalidateDataSource = async dataSourceId => {
const relatedInstances = get(store).filter(instance => { if (!dataSourceId) {
return instance.dataSourceId === dataSourceId return
}) }
relatedInstances?.forEach(instance => {
instance.refresh()
})
// Emit this as a window event, so parent screens which are iframing us in // Emit this as a window event, so parent screens which are iframing us in
// can also invalidate the same datasource // can also invalidate the same datasource
@ -77,6 +64,32 @@ export const createDataSourceStore = () => {
detail: { dataSourceId }, detail: { dataSourceId },
}) })
) )
let invalidations = [dataSourceId]
// Fetch related table IDs from table schema
const definition = await fetchTableDefinition(dataSourceId)
const schema = definition?.schema
if (schema) {
Object.values(schema).forEach(fieldSchema => {
if (fieldSchema.type === "link" && fieldSchema.tableId) {
invalidations.push(fieldSchema.tableId)
}
})
}
// Remove and dupes
invalidations = [...new Set(invalidations)]
// Invalidate all sources
invalidations.forEach(id => {
const relatedInstances = get(store).filter(instance => {
return instance.dataSourceId === id
})
relatedInstances?.forEach(instance => {
instance.refresh()
})
})
} }
return { return {