diff --git a/frontend/src/lib/components/apps/components/display/dbtable/AppDbExplorer.svelte b/frontend/src/lib/components/apps/components/display/dbtable/AppDbExplorer.svelte index 43493b9f87..d634942487 100644 --- a/frontend/src/lib/components/apps/components/display/dbtable/AppDbExplorer.svelte +++ b/frontend/src/lib/components/apps/components/display/dbtable/AppDbExplorer.svelte @@ -15,11 +15,12 @@ type TableMetadata, getPrimaryKeys, type ColumnDef, - type DbType + type DbType, + getTablesByResource } from './utils' import { getContext, tick } from 'svelte' import UpdateCell from './UpdateCell.svelte' - import { workspaceStore, type DBSchemas, type DBSchema } from '$lib/stores' + import { workspaceStore, type DBSchemas } from '$lib/stores' import Button from '$lib/components/common/button/Button.svelte' import { Plus } from 'lucide-svelte' import { Drawer, DrawerContent } from '$lib/components/common' @@ -44,16 +45,44 @@ export let render: boolean export let initializing: boolean = true + $: table = resolvedConfig.type.configuration?.[resolvedConfig.type?.selected]?.table as + | string + | undefined + + $: table !== null && render && clearColumns() + + function clearColumns() { + // We only want to clear the columns if the table has changed + if (!(lastTable && table && lastTable !== table) && !(lastTable && !table)) { + return + } + + const gridItem = findGridItem($app, id) + + if (!gridItem) { + return + } + + // @ts-ignore + gridItem.data.configuration.columnDefs = { value: [], type: 'static' } + + $app = { + ...$app + } + } + const resolvedConfig = initConfig( components['dbexplorercomponent'].initialData.configuration, configuration ) - $: computeInput( - resolvedConfig.columnDefs, - resolvedConfig.whereClause, - resolvedConfig.type.configuration[resolvedConfig.type.selected].resource - ) + $: resolvedConfig.type.selected && + render && + computeInput( + resolvedConfig.columnDefs, + resolvedConfig.whereClause, + resolvedConfig.type.configuration[resolvedConfig.type.selected].resource + ) let timeoutInput: NodeJS.Timeout | undefined = undefined @@ -83,7 +112,7 @@ let quicksearch = '' let aggrid: AppAggridExplorerTable - $: editorContext != undefined && $mode == 'dnd' && resolvedConfig.type && listTableIfAvailable() + $: editorContext != undefined && $mode == 'dnd' && resolvedConfig.type && listTables() $: editorContext != undefined && $mode == 'dnd' && @@ -168,8 +197,11 @@ }) } - async function listTableIfAvailable() { + async function listTables() { let resource = resolvedConfig.type.configuration?.[resolvedConfig.type.selected]?.resource + + if (!resource) return + if (lastResource === resource) return lastResource = resource const gridItem = findGridItem($app, id) @@ -212,7 +244,9 @@ resolvedConfig.type, { table: { - selectOptions: dbSchemas ? getTablesByResource(dbSchemas) : [], + selectOptions: dbSchemas + ? getTablesByResource(dbSchemas, resolvedConfig?.type?.selected) + : [], loading: false } } @@ -224,42 +258,6 @@ } catch (e) {} } - function getTablesByResource(schema: Partial>) { - const s = Object.values(schema)?.[0] - switch (resolvedConfig.type.selected) { - case 'postgresql': - if (s?.lang === 'postgresql') { - return Object.keys(s.schema?.public ?? s.schema ?? {}) - } - case 'mysql': - return Object.keys(Object.values(s?.schema ?? {})?.[0]) - case 'ms_sql_server': - return Object.keys(Object.values(s?.schema ?? {})?.[0]) - case 'snowflake': { - return Object.keys(Object.values(s?.schema ?? {})?.[0]) - } - - case 'bigquery': { - const paths: string[] = [] - for (const key in s?.schema) { - if (s?.schema.hasOwnProperty(key)) { - const subObj = s?.schema[key] - for (const subKey in subObj) { - if (subObj.hasOwnProperty(subKey)) { - paths.push(`${key}.${subKey}`) - } - } - } - } - - return paths - } - - default: - return [] - } - } - let datasource: IDatasource = { rowCount: 0, getRows: async function (params) { @@ -319,8 +317,8 @@ } let lastTable: string | undefined = undefined - let timeout: NodeJS.Timeout | undefined = undefined + async function listColumnsIfAvailable() { const selected = resolvedConfig.type.selected let table = resolvedConfig.type.configuration?.[resolvedConfig.type.selected]?.table @@ -328,6 +326,7 @@ if (lastTable === table) return lastTable = table + let tableMetadata = await loadTableMetaData( resolvedConfig.type.configuration[selected].resource, $workspaceStore, @@ -386,6 +385,7 @@ //@ts-ignore gridItem.data.configuration.columnDefs = { value: ncols, type: 'static' } gridItem.data = gridItem.data + $app = $app let oldS = $selectedComponent $selectedComponent = [] @@ -403,7 +403,7 @@ let isInsertable: boolean = false - $: $worldStore && connectToComponents() + $: $worldStore && render && connectToComponents() function connectToComponents() { if ($worldStore && datasource !== undefined) { @@ -414,6 +414,11 @@ { id: 'dbexplorer-count-' + id, next: (value) => { + if (value?.error) { + sendUserToast(value.error, true) + return + } + // MsSql response have an outer array, we need to flatten it if ( Array.isArray(value) && @@ -517,8 +522,8 @@ renderCount={refreshCount} {id} {quicksearch} - table={resolvedConfig?.type?.configuration?.[resolvedConfig?.type?.selected]?.table ?? ''} - resource={resolvedConfig?.type?.configuration?.[resolvedConfig?.type?.selected]?.resource ?? ''} + {table} + resource={resolvedConfig?.type?.configuration?.[resolvedConfig?.type?.selected]?.resource} resourceType={resolvedConfig?.type?.selected} columnDefs={resolvedConfig?.columnDefs} whereClause={resolvedConfig?.whereClause} diff --git a/frontend/src/lib/components/apps/components/display/dbtable/DbExplorerCount.svelte b/frontend/src/lib/components/apps/components/display/dbtable/DbExplorerCount.svelte index 2547cb3820..7cb0f1148e 100644 --- a/frontend/src/lib/components/apps/components/display/dbtable/DbExplorerCount.svelte +++ b/frontend/src/lib/components/apps/components/display/dbtable/DbExplorerCount.svelte @@ -9,8 +9,8 @@ import { getCountInput } from './queries/count' export let id: string - export let table: string - export let resource: string + export let table: string | undefined + export let resource: string | undefined export let renderCount: number export let quicksearch: string export let resourceType: string @@ -28,10 +28,20 @@ let runnableComponent: RunnableComponent let loading = false let input: AppInput | undefined = undefined - let lastTableCount = '' + let lastTableCount: string | undefined = undefined let renderCountLast = -1 let quicksearchLast: string | undefined = undefined + let localColumnDefs = columnDefs + let lastTable = table + + $: { + if (table !== lastTable) { + localColumnDefs = [] + lastTable = table + } + } + $: table && renderCount != undefined && quicksearch != undefined && computeCount() async function computeCount() { @@ -41,7 +51,7 @@ quicksearch == quicksearchLast ) return - if (table != '' && resource != '') { + if (table != undefined && resource !== undefined) { renderCountLast = renderCount lastTableCount = table quicksearchLast = quicksearch @@ -50,7 +60,7 @@ } async function getCount(resource: string, table: string, quicksearch: string) { - input = getCountInput(resource, table, resourceType as DbType, columnDefs, whereClause) + input = getCountInput(resource, table, resourceType as DbType, localColumnDefs, whereClause) await tick() diff --git a/frontend/src/lib/components/apps/components/display/dbtable/queries/select.ts b/frontend/src/lib/components/apps/components/display/dbtable/queries/select.ts index b0778490c7..992010fe81 100644 --- a/frontend/src/lib/components/apps/components/display/dbtable/queries/select.ts +++ b/frontend/src/lib/components/apps/components/display/dbtable/queries/select.ts @@ -69,7 +69,7 @@ function makeSnowflakeSelectQuery( ) return `CASE WHEN ? = '${column.field}' AND ? = FALSE THEN "${column.field}" END ASC, - CASE WHEN ? = '${column.field}' AND ? = TRUE THEN "${column.field}" END DESC` + CASE WHEN ? = '${column.field}' AND ? = TRUE THEN "${column.field}" END DESC` }) query += ` ORDER BY ${orderBy.join(',\n')}` diff --git a/frontend/src/lib/components/apps/components/display/dbtable/utils.ts b/frontend/src/lib/components/apps/components/display/dbtable/utils.ts index 2d65aa77c6..2bfab04f5d 100644 --- a/frontend/src/lib/components/apps/components/display/dbtable/utils.ts +++ b/frontend/src/lib/components/apps/components/display/dbtable/utils.ts @@ -657,3 +657,42 @@ export function getPrimaryKeys(tableMetadata?: TableMetadata): string[] { } return r ?? [] } + +export function getTablesByResource( + schema: Partial>, + dbType: DbType | undefined +): string[] { + const s = Object.values(schema)?.[0] + switch (dbType) { + case 'postgresql': + if (s?.lang === 'postgresql') { + return Object.keys(s.schema?.public ?? s.schema ?? {}) + } + case 'mysql': + return Object.keys(Object.values(s?.schema ?? {})?.[0]) + case 'ms_sql_server': + return Object.keys(Object.values(s?.schema ?? {})?.[0]) + case 'snowflake': { + return Object.keys(Object.values(s?.schema ?? {})?.[0]) + } + + case 'bigquery': { + const paths: string[] = [] + for (const key in s?.schema) { + if (s?.schema.hasOwnProperty(key)) { + const subObj = s?.schema[key] + for (const subKey in subObj) { + if (subObj.hasOwnProperty(subKey)) { + paths.push(`${key}.${subKey}`) + } + } + } + } + + return paths + } + + default: + return [] + } +} diff --git a/frontend/src/lib/components/apps/components/display/table/AppAggridExplorerTable.svelte b/frontend/src/lib/components/apps/components/display/table/AppAggridExplorerTable.svelte index 5095796a62..053cbeafa0 100644 --- a/frontend/src/lib/components/apps/components/display/table/AppAggridExplorerTable.svelte +++ b/frontend/src/lib/components/apps/components/display/table/AppAggridExplorerTable.svelte @@ -177,7 +177,7 @@ }, infiniteInitialRowCount: 100, cacheBlockSize: 100, - cacheOverflowSize: 2, + cacheOverflowSize: 10, maxBlocksInCache: 20, suppressColumnMoveAnimation: true, rowSelection: resolvedConfig?.multipleSelectable ? 'multiple' : 'single', @@ -197,6 +197,7 @@ }, onGridReady: (e) => { outputs?.ready.set(true) + $componentControl[id] = { agGrid: { api: e.api, columnApi: e.columnApi }, setSelectedIndex: (index) => { diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte index 282e4a1b2f..66bd7afc00 100644 --- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte @@ -192,7 +192,6 @@ let config = c.configuration as any const dbType = config?.type?.selected - let pg = config?.type?.configuration?.[dbType] if (pg && dbType) { @@ -208,6 +207,7 @@ input: getSelectInput(resourceValue, tableValue, columnDefs, whereClause, dbType), id: x.id }) + r.push({ input: getCountInput(resourceValue, tableValue, dbType, columnDefs, whereClause), id: x.id + '_count' diff --git a/frontend/src/lib/components/apps/editor/component/components.ts b/frontend/src/lib/components/apps/editor/component/components.ts index d9d767a4ca..8a4d5fa9eb 100644 --- a/frontend/src/lib/components/apps/editor/component/components.ts +++ b/frontend/src/lib/components/apps/editor/component/components.ts @@ -3373,7 +3373,7 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm' } as StaticAppInput, table: { fieldType: 'select', - subfieldType: 'db-table', + subFieldType: 'db-table', type: 'static', selectOptions: [], value: undefined @@ -3388,7 +3388,7 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm' } as StaticAppInput, table: { fieldType: 'select', - subfieldType: 'db-table', + subFieldType: 'db-table', type: 'static', selectOptions: [], value: undefined @@ -3403,7 +3403,7 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm' } as StaticAppInput, table: { fieldType: 'select', - subfieldType: 'db-table', + subFieldType: 'db-table', type: 'static', selectOptions: [], value: undefined @@ -3418,7 +3418,7 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm' } as StaticAppInput, table: { fieldType: 'select', - subfieldType: 'db-table', + subFieldType: 'db-table', type: 'static', selectOptions: [], value: undefined @@ -3433,7 +3433,7 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm' } as StaticAppInput, table: { fieldType: 'select', - subfieldType: 'db-table', + subFieldType: 'db-table', type: 'static', selectOptions: [], value: undefined diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte index 55824c7252..0793429a60 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte @@ -1,7 +1,7 @@
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/DBTableSelect.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/DBTableSelect.svelte new file mode 100644 index 0000000000..110ab76784 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/DBTableSelect.svelte @@ -0,0 +1,47 @@ + + + + +{#if selectOptions && componentInput} + +{/if} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte index 8da91d8cae..84378e0a3d 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte @@ -21,6 +21,7 @@ import DBExplorerWizard from '$lib/components/wizards/DBExplorerWizard.svelte' import Label from '$lib/components/Label.svelte' import DateTimeInput from '$lib/components/DateTimeInput.svelte' + import DBTableSelect from './DBTableSelect.svelte' export let componentInput: StaticInput | undefined export let fieldType: InputType | undefined = undefined @@ -50,19 +51,23 @@ {:else if fieldType === 'boolean'} {:else if fieldType === 'select' && selectOptions} - + {#if subFieldType === 'db-table'} + + {:else} + + {/if} {:else if fieldType === 'icon-select'} {:else if fieldType === 'tab-select'}