Type table store

This commit is contained in:
Adria Navarro 2024-12-19 16:53:51 +01:00
parent bbd69ce318
commit c61cf5d583
1 changed files with 81 additions and 56 deletions

View File

@ -1,30 +1,64 @@
import { FieldType } from "@budibase/types" import {
FieldSchema,
FieldType,
SaveTableRequest,
Table,
} from "@budibase/types"
import { SWITCHABLE_TYPES } from "@budibase/shared-core" import { SWITCHABLE_TYPES } from "@budibase/shared-core"
import { get, writable, derived } from "svelte/store" import { get, derived, Writable } from "svelte/store"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { API } from "api" import { API } from "api"
import { DerivedBudiStore } from "stores/BudiStore"
export function createTablesStore() { interface BuilderTableStore {
const store = writable({ list: Table[]
list: [], selectedTableId?: string
selectedTableId: null, }
})
const derivedStore = derived(store, $store => ({
...$store,
selected: $store.list?.find(table => table._id === $store.selectedTableId),
}))
const fetch = async () => { interface DerivedTableStore extends BuilderTableStore {
selected?: Table
}
export class TableStore extends DerivedBudiStore<
BuilderTableStore,
DerivedTableStore
> {
constructor() {
const makeDerivedStore = (store: Writable<BuilderTableStore>) => {
return derived(store, $store => ({
...$store,
selected: $store.list?.find(
table => table._id === $store.selectedTableId
),
}))
}
super(
{
list: [],
selectedTableId: undefined,
},
makeDerivedStore
)
this.select = this.select.bind(this)
}
async init() {
return this.fetch()
}
async fetch() {
const tables = await API.getTables() const tables = await API.getTables()
store.update(state => ({ this.store.update(state => ({
...state, ...state,
list: tables, list: tables,
})) }))
} }
const singleFetch = async tableId => { private async singleFetch(tableId: string) {
const table = await API.getTable(tableId) const table = await API.getTable(tableId)
store.update(state => { this.store.update(state => {
const list = [] const list = []
// update the list, keep order accurate // update the list, keep order accurate
for (let tbl of state.list) { for (let tbl of state.list) {
@ -39,16 +73,16 @@ export function createTablesStore() {
}) })
} }
const select = tableId => { select(tableId: string | undefined) {
store.update(state => ({ this.store.update(state => ({
...state, ...state,
selectedTableId: tableId, selectedTableId: tableId,
})) }))
} }
const save = async table => { async save(table: Table) {
const updatedTable = cloneDeep(table) const updatedTable: SaveTableRequest = cloneDeep(table)
const oldTable = get(store).list.filter(t => t._id === table._id)[0] const oldTable = get(this.store).list.filter(t => t._id === table._id)[0]
const fieldNames = [] const fieldNames = []
// Update any renamed schema keys to reflect their names // Update any renamed schema keys to reflect their names
@ -79,8 +113,8 @@ export function createTablesStore() {
} }
const savedTable = await API.saveTable(updatedTable) const savedTable = await API.saveTable(updatedTable)
replaceTable(savedTable._id, savedTable) this.replaceTable(savedTable._id, savedTable)
select(savedTable._id) this.select(savedTable._id)
// make sure tables up to date (related) // make sure tables up to date (related)
let newTableIds = [] let newTableIds = []
for (let column of Object.values(updatedTable?.schema || {})) { for (let column of Object.values(updatedTable?.schema || {})) {
@ -99,28 +133,33 @@ export function createTablesStore() {
const tableIdsToFetch = [...new Set([...newTableIds, ...oldTableIds])] const tableIdsToFetch = [...new Set([...newTableIds, ...oldTableIds])]
// too many tables to fetch, just get all // too many tables to fetch, just get all
if (tableIdsToFetch.length > 3) { if (tableIdsToFetch.length > 3) {
await fetch() await this.fetch()
} else { } else {
await Promise.all(tableIdsToFetch.map(id => singleFetch(id))) await Promise.all(tableIdsToFetch.map(id => this.singleFetch(id)))
} }
return savedTable return savedTable
} }
const deleteTable = async table => { async delete(table: { _id: string; _rev: any }) {
if (!table?._id) { if (!table?._id) {
return return
} }
await API.deleteTable(table._id, table._rev || "rev") await API.deleteTable(table._id, table._rev || "rev")
replaceTable(table._id, null) this.replaceTable(table._id, null)
} }
const saveField = async ({ async saveField({
originalName, originalName,
field, field,
primaryDisplay = false, primaryDisplay = false,
indexes, indexes,
}) => { }: {
let draft = cloneDeep(get(derivedStore).selected) originalName: string
field: FieldSchema
primaryDisplay: boolean
indexes: Record<string, any>
}) {
const draft: SaveTableRequest = cloneDeep(get(this.derivedStore).selected!)
// delete the original if renaming // delete the original if renaming
// need to handle if the column had no name, empty string // need to handle if the column had no name, empty string
@ -139,7 +178,7 @@ export function createTablesStore() {
const fields = Object.keys(draft.schema) const fields = Object.keys(draft.schema)
// pick another display column randomly if unselecting // pick another display column randomly if unselecting
draft.primaryDisplay = fields.filter( draft.primaryDisplay = fields.filter(
name => name !== originalName || name !== field name => name !== originalName || name !== field.name
)[0] )[0]
} }
if (indexes) { if (indexes) {
@ -150,24 +189,24 @@ export function createTablesStore() {
[field.name]: cloneDeep(field), [field.name]: cloneDeep(field),
} }
await save(draft) await this.save(draft)
} }
const deleteField = async field => { async deleteField(field: { name: string | number }) {
let draft = cloneDeep(get(derivedStore).selected) let draft = cloneDeep(get(this.derivedStore).selected!)
delete draft.schema[field.name] delete draft.schema[field.name]
await save(draft) await this.save(draft)
} }
// Handles external updates of tables // Handles external updates of tables
const replaceTable = (tableId, table) => { replaceTable(tableId: string | undefined, table: Table | null) {
if (!tableId) { if (!tableId) {
return return
} }
// Handle deletion // Handle deletion
if (!table) { if (!table) {
store.update(state => ({ this.store.update(state => ({
...state, ...state,
list: state.list.filter(x => x._id !== tableId), list: state.list.filter(x => x._id !== tableId),
})) }))
@ -175,9 +214,9 @@ export function createTablesStore() {
} }
// Add new table // Add new table
const index = get(store).list.findIndex(x => x._id === table._id) const index = get(this.store).list.findIndex(x => x._id === table._id)
if (index === -1) { if (index === -1) {
store.update(state => ({ this.store.update(state => ({
...state, ...state,
list: [...state.list, table], list: [...state.list, table],
})) }))
@ -188,7 +227,7 @@ export function createTablesStore() {
// This function has to merge state as there discrepancies with the table // This function has to merge state as there discrepancies with the table
// API endpoints. The table list endpoint and get table endpoint use the // API endpoints. The table list endpoint and get table endpoint use the
// "type" property to mean different things. // "type" property to mean different things.
store.update(state => { this.store.update(state => {
state.list[index] = { state.list[index] = {
...table, ...table,
type: state.list[index].type, type: state.list[index].type,
@ -198,26 +237,12 @@ export function createTablesStore() {
} }
} }
const removeDatasourceTables = datasourceId => { removeDatasourceTables(datasourceId: any) {
store.update(state => ({ this.store.update(state => ({
...state, ...state,
list: state.list.filter(table => table.sourceId !== datasourceId), list: state.list.filter(table => table.sourceId !== datasourceId),
})) }))
} }
return {
...store,
subscribe: derivedStore.subscribe,
fetch,
init: fetch,
select,
save,
delete: deleteTable,
saveField,
deleteField,
replaceTable,
removeDatasourceTables,
}
} }
export const tables = createTablesStore() export const tables = new TableStore()