This is an automated email from the ASF dual-hosted git repository. jli pushed a commit to branch 4.1 in repository https://gitbox.apache.org/repos/asf/superset.git
commit 69dd88720e9b879db5026e7cfa3cfa5f8635bad4 Author: Usiel Riedl <[email protected]> AuthorDate: Fri Aug 23 08:07:59 2024 +0800 feat(sqllab): Adds refresh button to table metadata in SQL Lab (#29974) (cherry picked from commit 9d5268ab6dbd6d93b9bb4047cddc99afc510d3c7) --- .../components/TableElement/TableElement.test.tsx | 37 ++++++++++++++++++---- .../src/SqlLab/components/TableElement/index.tsx | 17 ++++++++-- superset-frontend/src/hooks/apiResources/tables.ts | 7 ++++ 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx index 30f41e5ee3..2f391c269b 100644 --- a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx +++ b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx @@ -51,11 +51,13 @@ const getTableMetadataEndpoint = /\/api\/v1\/database\/\d+\/table_metadata\/(?:\?.*)?$/; const getExtraTableMetadataEndpoint = /\/api\/v1\/database\/\d+\/table_metadata\/extra\/(?:\?.*)?$/; -const updateTableSchemaEndpoint = 'glob:*/tableschemaview/*/expanded'; +const updateTableSchemaExpandedEndpoint = 'glob:*/tableschemaview/*/expanded'; +const updateTableSchemaEndpoint = 'glob:*/tableschemaview/'; beforeEach(() => { fetchMock.get(getTableMetadataEndpoint, table); fetchMock.get(getExtraTableMetadataEndpoint, {}); + fetchMock.post(updateTableSchemaExpandedEndpoint, {}); fetchMock.post(updateTableSchemaEndpoint, {}); }); @@ -84,7 +86,7 @@ test('has 4 IconTooltip elements', async () => { initialState, }); await waitFor(() => - expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(4), + expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(5), ); }); @@ -104,7 +106,7 @@ test('fades table', async () => { initialState, }); await waitFor(() => - expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(4), + expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(5), ); const style = window.getComputedStyle(getAllByTestId('fade')[0]); expect(style.opacity).toBe('0'); @@ -125,7 +127,7 @@ test('sorts columns', async () => { }, ); await waitFor(() => - expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(4), + expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(5), ); expect( getAllByTestId('mock-column-element').map(el => el.textContent), @@ -154,7 +156,7 @@ test('removes the table', async () => { }, ); await waitFor(() => - expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(4), + expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(5), ); expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(0); fireEvent.click(getByText('Remove table preview')); @@ -174,6 +176,29 @@ test('fetches table metadata when expanded', async () => { await waitFor(() => expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(1), ); - expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(0); + expect(fetchMock.calls(updateTableSchemaExpandedEndpoint)).toHaveLength(0); expect(fetchMock.calls(getExtraTableMetadataEndpoint)).toHaveLength(1); }); + +test('refreshes table metadata when triggered', async () => { + const { getAllByTestId, getByText } = render( + <TableElement {...mockedProps} />, + { + useRedux: true, + initialState, + }, + ); + await waitFor(() => + expect(getAllByTestId('mock-icon-tooltip')).toHaveLength(5), + ); + expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(0); + expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(1); + + fireEvent.click(getByText('Refresh table schema')); + await waitFor(() => + expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(2), + ); + await waitFor(() => + expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1), + ); +}); diff --git a/superset-frontend/src/SqlLab/components/TableElement/index.tsx b/superset-frontend/src/SqlLab/components/TableElement/index.tsx index faa56db6be..824c9ec3c4 100644 --- a/superset-frontend/src/SqlLab/components/TableElement/index.tsx +++ b/superset-frontend/src/SqlLab/components/TableElement/index.tsx @@ -32,6 +32,7 @@ import { syncTable, } from 'src/SqlLab/actions/sqlLab'; import { + tableApiUtil, useTableExtendedMetadataQuery, useTableMetadataQuery, } from 'src/hooks/apiResources'; @@ -107,7 +108,7 @@ const TableElement = ({ table, ...props }: TableElementProps) => { const { currentData: tableMetadata, isSuccess: isMetadataSuccess, - isLoading: isMetadataLoading, + isFetching: isMetadataFetching, isError: hasMetadataError, } = useTableMetadataQuery( { @@ -177,6 +178,13 @@ const TableElement = ({ table, ...props }: TableElementProps) => { setSortColumns(prevState => !prevState); }; + const refreshTableMetadata = () => { + dispatch( + tableApiUtil.invalidateTags([{ type: 'TableMetadatas', id: name }]), + ); + dispatch(syncTable(table, tableData)); + }; + const renderWell = () => { let partitions; let metadata; @@ -268,6 +276,11 @@ const TableElement = ({ table, ...props }: TableElementProps) => { } `} > + <IconTooltip + className="fa fa-refresh pull-left m-l-2 pointer" + onClick={refreshTableMetadata} + tooltip={t('Refresh table schema')} + /> {keyLink} <IconTooltip className={ @@ -341,7 +354,7 @@ const TableElement = ({ table, ...props }: TableElementProps) => { </Tooltip> <div className="pull-right header-right-side"> - {isMetadataLoading || isExtraMetadataLoading ? ( + {isMetadataFetching || isExtraMetadataLoading ? ( <Loading position="inline" /> ) : ( <Fade diff --git a/superset-frontend/src/hooks/apiResources/tables.ts b/superset-frontend/src/hooks/apiResources/tables.ts index f2accf499c..86b080745f 100644 --- a/superset-frontend/src/hooks/apiResources/tables.ts +++ b/superset-frontend/src/hooks/apiResources/tables.ts @@ -117,6 +117,13 @@ const tableApi = api.injectEndpoints({ }), }), tableMetadata: builder.query<TableMetaData, FetchTableMetadataQueryParams>({ + providesTags: result => + result + ? [ + { type: 'TableMetadatas', id: result.name }, + { type: 'TableMetadatas', id: 'LIST' }, + ] + : [{ type: 'TableMetadatas', id: 'LIST' }], query: ({ dbId, catalog, schema, table }) => ({ endpoint: `/api/v1/database/${dbId}/table_metadata/${toQueryString({ name: table,
