Type table store
This commit is contained in:
parent
bbd69ce318
commit
c61cf5d583
|
@ -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()
|
Loading…
Reference in New Issue