diff --git a/common/types/data_connections.ts b/common/types/data_connections.ts index 9293c60048..d93ba8bf23 100644 --- a/common/types/data_connections.ts +++ b/common/types/data_connections.ts @@ -39,8 +39,8 @@ export interface AssociatedObject { name: string; database: string; type: AccelerationIndexType | 'table'; - accelerations: Acceleration[]; - columns?: TableColumn[]; + accelerations: CachedAcceleration[]; + columns?: CachedColumn[]; } export type Role = EuiComboBoxOptionOption; diff --git a/public/components/datasources/components/__tests__/__snapshots__/associated_objects_tab.test.tsx.snap b/public/components/datasources/components/__tests__/__snapshots__/associated_objects_tab.test.tsx.snap index a2f438767d..43d22c3ab3 100644 --- a/public/components/datasources/components/__tests__/__snapshots__/associated_objects_tab.test.tsx.snap +++ b/public/components/datasources/components/__tests__/__snapshots__/associated_objects_tab.test.tsx.snap @@ -691,6 +691,7 @@ exports[`AssociatedObjectsTab Component renders correctly with associated object ] } data-test-subj="associatedObjectsTable" + hasActions={true} items={ Array [ Object { @@ -773,7 +774,7 @@ exports[`AssociatedObjectsTab Component renders correctly with associated object Object { "box": Object { "incremental": true, - "placeholder": "database:database_1 database: database_2 accelerations:skipping_index_1", + "placeholder": "accelerations:skipping_index_1", "schema": Object { "fields": Object { "database": Object { @@ -815,14 +816,14 @@ exports[`AssociatedObjectsTab Component renders correctly with associated object }, } } - tableLayout="fixed" + tableLayout="auto" >
@@ -1253,6 +1254,7 @@ exports[`AssociatedObjectsTab Component renders correctly with associated object ] } data-test-subj="associatedObjectsTable" + hasActions={true} items={ Array [ Object { @@ -1345,7 +1347,7 @@ exports[`AssociatedObjectsTab Component renders correctly with associated object }, } } - tableLayout="fixed" + tableLayout="auto" >
diff --git a/public/components/datasources/components/__tests__/acceleration_table.test.tsx b/public/components/datasources/components/__tests__/acceleration_table.test.tsx index a8f8516397..8c8ef6eabc 100644 --- a/public/components/datasources/components/__tests__/acceleration_table.test.tsx +++ b/public/components/datasources/components/__tests__/acceleration_table.test.tsx @@ -80,6 +80,7 @@ jest.mock('../../../../framework/catalog_cache/cache_loader', () => ({ jest.mock('../../../../plugin', () => ({ getRenderAccelerationDetailsFlyout: jest.fn(() => jest.fn()), + getRenderCreateAccelerationFlyout: jest.fn(() => jest.fn()), })); describe('AccelerationTable Component', () => { diff --git a/public/components/datasources/components/__tests__/associated_objects_flyout.test.tsx b/public/components/datasources/components/__tests__/associated_objects_flyout.test.tsx index 713cc363a6..a561452557 100644 --- a/public/components/datasources/components/__tests__/associated_objects_flyout.test.tsx +++ b/public/components/datasources/components/__tests__/associated_objects_flyout.test.tsx @@ -10,12 +10,14 @@ import { AssociatedObjectsDetailsFlyout } from '../manage/associated_objects/ass import * as plugin from '../../../../plugin'; import { act } from '@testing-library/react'; import { mockAssociatedObjects } from '../../../../../test/datasources'; +import { getAccelerationName } from '../manage/accelerations/utils/acceleration_utils'; configure({ adapter: new Adapter() }); jest.mock('../../../../plugin', () => ({ getRenderAccelerationDetailsFlyout: jest.fn(() => jest.fn()), getRenderAssociatedObjectsDetailsFlyout: jest.fn(() => jest.fn()), + getRenderCreateAccelerationFlyout: jest.fn(() => jest.fn()), })); describe('AssociatedObjectsDetailsFlyout Integration Tests', () => { @@ -26,7 +28,9 @@ describe('AssociatedObjectsDetailsFlyout Integration Tests', () => { }); it('renders acceleration details correctly and triggers flyout on click', () => { - const wrapper = mount(); + const wrapper = mount( + + ); expect(wrapper.find('EuiInMemoryTable').at(0).find('EuiLink').length).toBeGreaterThan(0); wrapper.find('EuiInMemoryTable').at(0).find('EuiLink').first().simulate('click'); @@ -38,13 +42,16 @@ describe('AssociatedObjectsDetailsFlyout Integration Tests', () => { ...mockTableDetail, accelerations: [], columns: [ - { name: 'column1', dataType: 'string' }, - { name: 'column2', dataType: 'number' }, + { fieldName: 'column1', dataType: 'string' }, + { fieldName: 'column2', dataType: 'number' }, ], }; const wrapper = mount( - + ); expect(wrapper.text()).toContain('You have no accelerations'); @@ -54,16 +61,20 @@ describe('AssociatedObjectsDetailsFlyout Integration Tests', () => { }); it('renders schema table correctly with column data', () => { - const wrapper = mount(); + const wrapper = mount( + + ); expect(wrapper.find('EuiInMemoryTable').at(1).exists()).toBe(true); expect(wrapper.find('EuiInMemoryTable').at(1).text()).toContain( - mockTableDetail.columns[0].name + mockTableDetail.columns[0].fieldName ); }); it('triggers details flyout on acceleration link click', async () => { - const wrapper = mount(); + const wrapper = mount( + + ); await act(async () => { // Wait a tick for async updates @@ -71,7 +82,7 @@ describe('AssociatedObjectsDetailsFlyout Integration Tests', () => { wrapper.update(); }); - const accName = mockTableDetail.accelerations[0]?.name; + const accName = getAccelerationName(mockTableDetail.accelerations[0], 'flint_s3'); const accLink = wrapper .find('EuiLink') .findWhere((node) => node.text() === accName) diff --git a/public/components/datasources/components/__tests__/associated_objects_tab.test.tsx b/public/components/datasources/components/__tests__/associated_objects_tab.test.tsx index e553a5fc81..956e7a8cb9 100644 --- a/public/components/datasources/components/__tests__/associated_objects_tab.test.tsx +++ b/public/components/datasources/components/__tests__/associated_objects_tab.test.tsx @@ -21,6 +21,7 @@ import { DirectQueryLoadingStatus } from '../../../../../common/types/explorer'; jest.mock('../../../../plugin', () => ({ getRenderAccelerationDetailsFlyout: jest.fn(() => jest.fn()), getRenderAssociatedObjectsDetailsFlyout: jest.fn(() => jest.fn()), + getRenderCreateAccelerationFlyout: jest.fn(() => jest.fn()), })); describe('AssociatedObjectsTab Component', () => { diff --git a/public/components/datasources/components/manage/accelerations/acceleration_table.tsx b/public/components/datasources/components/manage/accelerations/acceleration_table.tsx index 34c46ed849..dcd1ac56d6 100644 --- a/public/components/datasources/components/manage/accelerations/acceleration_table.tsx +++ b/public/components/datasources/components/manage/accelerations/acceleration_table.tsx @@ -25,7 +25,10 @@ import { } from '../../../../../../common/types/data_connections'; import { DirectQueryLoadingStatus } from '../../../../../../common/types/explorer'; import { isCatalogCacheFetching } from '../associated_objects/utils/associated_objects_tab_utils'; -import { getRenderAccelerationDetailsFlyout } from '../../../../../plugin'; +import { + getRenderAccelerationDetailsFlyout, + getRenderCreateAccelerationFlyout, +} from '../../../../../plugin'; import { ACC_LOADING_MSG, ACC_PANEL_DESC, @@ -118,11 +121,9 @@ export const AccelerationTable = ({ }; const CreateButton = () => { - // TODO: Create button should call create_acceleration.tsx, which will be brought - // over from dashboards-query-workbench/public/components/acceleration/create/create_accelerations.tsx return ( <> - console.log('clicked on create accelerations button')} fill> + renderCreateAccelerationFlyout(dataSourceName)} fill> Create acceleration @@ -204,7 +205,7 @@ export const AccelerationTable = ({ name: 'Name', sortable: true, render: (indexName: string, acceleration: CachedAcceleration) => { - const displayName = getAccelerationName(indexName, acceleration, dataSourceName); + const displayName = getAccelerationName(acceleration, dataSourceName); return ( { @@ -299,6 +300,7 @@ export const AccelerationTable = ({ }; const renderAccelerationDetailsFlyout = getRenderAccelerationDetailsFlyout(); + const renderCreateAccelerationFlyout = getRenderCreateAccelerationFlyout(); return ( <> diff --git a/public/components/datasources/components/manage/accelerations/utils/acceleration_utils.tsx b/public/components/datasources/components/manage/accelerations/utils/acceleration_utils.tsx index 85cc1b1da9..145dc889be 100644 --- a/public/components/datasources/components/manage/accelerations/utils/acceleration_utils.tsx +++ b/public/components/datasources/components/manage/accelerations/utils/acceleration_utils.tsx @@ -17,13 +17,10 @@ export const ACC_PANEL_DESC = 'Accelerations optimize query performance by indexing external data into OpenSearch.'; export const ACC_LOADING_MSG = 'Loading/Refreshing accelerations...'; -export const getAccelerationName = ( - indexName: string, - acceleration: CachedAcceleration, - datasource: string -) => { +export const getAccelerationName = (acceleration: CachedAcceleration, datasource: string) => { return ( - indexName || `${datasource}_${acceleration.database}_${acceleration.table}`.replace(/\s+/g, '_') + acceleration.indexName || + `${datasource}_${acceleration.database}_${acceleration.table}`.replace(/\s+/g, '_') ); }; diff --git a/public/components/datasources/components/manage/associated_objects/associated_objects_details_flyout.tsx b/public/components/datasources/components/manage/associated_objects/associated_objects_details_flyout.tsx index 8b10a19c9d..73ea3b0278 100644 --- a/public/components/datasources/components/manage/associated_objects/associated_objects_details_flyout.tsx +++ b/public/components/datasources/components/manage/associated_objects/associated_objects_details_flyout.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { EuiFlyoutBody, EuiFlyoutHeader, @@ -24,31 +24,46 @@ import { EuiButton, EuiEmptyPrompt, } from '@elastic/eui'; -import { AssociatedObject } from 'common/types/data_connections'; import { i18n } from '@osd/i18n'; import { - onAccelerateButtonClick, - onDeleteButtonClick, + AssociatedObject, + CachedAcceleration, + CachedColumn, +} from '../../../../../../common/types/data_connections'; +import { + isCatalogCacheFetching, redirectToExplorerWithDataSrc, } from './utils/associated_objects_tab_utils'; -import { getRenderAccelerationDetailsFlyout } from '../../../../../plugin'; -import { AccelerationStatus } from '../accelerations/utils/acceleration_utils'; +import { + getRenderAccelerationDetailsFlyout, + getRenderCreateAccelerationFlyout, +} from '../../../../../plugin'; +import { AccelerationStatus, getAccelerationName } from '../accelerations/utils/acceleration_utils'; import { ACCE_NO_DATA_TITLE, ACCE_NO_DATA_DESCRIPTION, CREATE_ACCELERATION_DESCRIPTION, } from '../associated_objects/utils/associated_objects_tab_utils'; import { DATA_SOURCE_TYPES } from '../../../../../../common/constants/data_sources'; +import { useLoadTableColumnsToCache } from '../../../../../../public/framework/catalog_cache/cache_loader'; +import { CatalogCacheManager } from '../../../../../../public/framework/catalog_cache/cache_manager'; +import { DirectQueryLoadingStatus } from '../../../../../../common/types/explorer'; export interface AssociatedObjectsFlyoutProps { tableDetail: AssociatedObject; + datasourceName: string; resetFlyout: () => void; } export const AssociatedObjectsDetailsFlyout = ({ tableDetail, + datasourceName, resetFlyout, }: AssociatedObjectsFlyoutProps) => { + const { loadStatus, startLoading } = useLoadTableColumnsToCache(); + const [tableColumns, setTableColumns] = useState([]); + const [schemaData, setSchemaData] = useState([]); + const DiscoverButton = () => { // TODO: display button if can be sent to discover return ( @@ -71,20 +86,16 @@ export const AssociatedObjectsDetailsFlyout = ({ const AccelerateButton = () => { return ( - + + renderCreateAccelerationFlyout(datasourceName, tableDetail.database, tableDetail.name) + } + > ); }; - const DeleteButton = () => { - return ( - - - - ); - }; - const DetailComponent = (detailProps: { title: string; description: any }) => { const { title, description } = detailProps; return ( @@ -124,21 +135,27 @@ export const AssociatedObjectsDetailsFlyout = ({ id: index, })); - const schemaData = tableDetail.columns - ? tableDetail.columns.map((column, index) => ({ - ...column, - id: index, - })) - : {}; - const accelerationColumns = [ { field: 'name', name: 'Name', 'data-test-subj': 'accelerationName', - render: (name: string, item: AssociatedObject) => ( - renderAccelerationDetailsFlyout(item)}>{name} - ), + render: (_: string, item: CachedAcceleration) => { + const name = getAccelerationName(item, datasourceName); + return ( + + renderAccelerationDetailsFlyout({ + index: name, + acceleration: item, + dataSourceName: datasourceName, + }) + } + > + {name} + + ); + }, }, { field: 'status', @@ -171,7 +188,9 @@ export const AssociatedObjectsDetailsFlyout = ({ window.open('https://example.com', '_blank')} + onClick={() => + renderCreateAccelerationFlyout(datasourceName, tableDetail.database, tableDetail.name) + } iconType="popout" iconSide="left" > @@ -198,6 +217,37 @@ export const AssociatedObjectsDetailsFlyout = ({ const renderAccelerationDetailsFlyout = getRenderAccelerationDetailsFlyout(); + useEffect(() => { + if (tableDetail && !tableDetail.columns) { + startLoading(datasourceName, tableDetail.database, tableDetail.name); + } else if (tableDetail && tableDetail.columns) { + setTableColumns(tableDetail.columns); + } + }, []); + + useEffect(() => { + if (loadStatus.toLowerCase() === DirectQueryLoadingStatus.SUCCESS) { + const columns = CatalogCacheManager.getTable( + datasourceName, + tableDetail.database, + tableDetail.name + ).columns; + setTableColumns(columns); + } + }, [loadStatus]); + + useEffect(() => { + setSchemaData( + tableColumns?.map((column, index) => ({ + name: column.fieldName, + dataType: column.dataType, + id: index, + })) + ); + }, [tableColumns]); + + const renderCreateAccelerationFlyout = getRenderCreateAccelerationFlyout(); + return ( <> @@ -213,9 +263,6 @@ export const AssociatedObjectsDetailsFlyout = ({ - - - @@ -241,6 +288,7 @@ export const AssociatedObjectsDetailsFlyout = ({ columns={schemaColumns} pagination={true} sorting={true} + loading={isCatalogCacheFetching(loadStatus)} /> diff --git a/public/components/datasources/components/manage/associated_objects/associated_objects_tab.tsx b/public/components/datasources/components/manage/associated_objects/associated_objects_tab.tsx index cb992f120a..baad05349a 100644 --- a/public/components/datasources/components/manage/associated_objects/associated_objects_tab.tsx +++ b/public/components/datasources/components/manage/associated_objects/associated_objects_tab.tsx @@ -264,8 +264,9 @@ export const AssociatedObjectsTab: React.FC = (props) name: table.name, database: selectedDatabase, type: 'table', - // Temporary dummy array - accelerations: [], + accelerations: cachedAccelerations.filter( + (acceleration) => acceleration.table === table.name + ), columns: table.columns, }; }); @@ -273,8 +274,8 @@ export const AssociatedObjectsTab: React.FC = (props) .filter((acceleration: CachedAcceleration) => acceleration.database === selectedDatabase) .map((acceleration: CachedAcceleration) => ({ datasource: datasource.name, - id: getAccelerationName(acceleration.indexName, acceleration, datasource.name), - name: getAccelerationName(acceleration.indexName, acceleration, datasource.name), + id: acceleration.indexName, + name: getAccelerationName(acceleration, datasource.name), database: acceleration.database, type: ACCELERATION_INDEX_TYPES.find((accelType) => accelType.value === acceleration.type)! .value, diff --git a/public/components/datasources/components/manage/associated_objects/modules/associated_objects_table.tsx b/public/components/datasources/components/manage/associated_objects/modules/associated_objects_table.tsx index 4334a71dfd..11c64e0fd5 100644 --- a/public/components/datasources/components/manage/associated_objects/modules/associated_objects_table.tsx +++ b/public/components/datasources/components/manage/associated_objects/modules/associated_objects_table.tsx @@ -10,6 +10,7 @@ import { EuiLink, SearchFilterConfig, EuiTableFieldDataColumnType, + EuiButtonEmpty, } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { @@ -19,6 +20,7 @@ import { import { getRenderAccelerationDetailsFlyout, getRenderAssociatedObjectsDetailsFlyout, + getRenderCreateAccelerationFlyout, } from '../../../../../../plugin'; import { ASSC_OBJ_TABLE_ACC_COLUMN_NAME, @@ -68,21 +70,20 @@ export const AssociatedObjectsTable = (props: AssociatedObjectsTableProps) => { { if (item.type === 'table') { - renderAssociatedObjectsDetailsFlyout(item); + renderAssociatedObjectsDetailsFlyout({ + tableDetail: item, + datasourceName, + }); } else { - const acceleration = cachedAccelerations.find( - (acc) => getAccelerationName(acc.indexName, acc, datasourceName) === name - ); + const acceleration = cachedAccelerations.find((acc) => acc.indexName === item.id); console.log(acceleration); - renderAccelerationDetailsFlyout({ - indexName: getAccelerationName( - acceleration?.indexName, + if (acceleration) { + renderAccelerationDetailsFlyout({ + index: getAccelerationName(acceleration, datasourceName), acceleration, - datasourceName - ), - acceleration, - dataSourceName: datasourceName, - }); + dataSourceName: datasourceName, + }); + } } }} > @@ -114,17 +115,39 @@ export const AssociatedObjectsTable = (props: AssociatedObjectsTableProps) => { defaultMessage: 'Accelerations', }), sortable: true, - render: (accelerations: string[]) => { - return accelerations.length > 0 - ? accelerations.map((acceleration, index) => ( - - renderAccelerationDetailsFlyout(acceleration)}> - {acceleration.name} - - {index < accelerations.length - 1 ? ', ' : ''} - - )) - : '-'; + // align: 'center', + render: (accelerations: CachedAcceleration[], obj: AssociatedObject) => { + if (accelerations.length === 0) { + return '-'; + } else if (accelerations.length === 1) { + const name = getAccelerationName(accelerations[0], datasourceName); + return ( + { + renderAccelerationDetailsFlyout({ + index: name, + acceleration: accelerations[0], + dataSourceName: datasourceName, + }); + }} + > + {name} + + ); + } + return ( + { + renderAssociatedObjectsDetailsFlyout({ + tableDetail: obj, + datasourceName, + }); + }} + size="xs" + > + View all {accelerations.length} + + ); }, }, { @@ -174,7 +197,8 @@ export const AssociatedObjectsTable = (props: AssociatedObjectsTableProps) => { type: 'icon', icon: 'bolt', available: (item: AssociatedObject) => item.type === 'table', - onClick: (item: AssociatedObject) => console.log('Accelerate', item), + onClick: (item: AssociatedObject) => + renderCreateAccelerationFlyout(datasourceName, item.database, item.name), }, ], }, @@ -266,6 +290,7 @@ export const AssociatedObjectsTable = (props: AssociatedObjectsTableProps) => { const renderAccelerationDetailsFlyout = getRenderAccelerationDetailsFlyout(); const renderAssociatedObjectsDetailsFlyout = getRenderAssociatedObjectsDetailsFlyout(); + const renderCreateAccelerationFlyout = getRenderCreateAccelerationFlyout(); return ( { search={tableSearch} pagination={pagination} sorting={sorting} + hasActions={true} + tableLayout="auto" data-test-subj={ASSC_OBJ_TABLE_SUBJ} /> ); diff --git a/public/components/datasources/components/manage/associated_objects/utils/associated_objects_tab_utils.tsx b/public/components/datasources/components/manage/associated_objects/utils/associated_objects_tab_utils.tsx index 3604d797a8..25f0d602b2 100644 --- a/public/components/datasources/components/manage/associated_objects/utils/associated_objects_tab_utils.tsx +++ b/public/components/datasources/components/manage/associated_objects/utils/associated_objects_tab_utils.tsx @@ -15,8 +15,7 @@ export const ASSC_OBJ_TABLE_SUBJ = 'associatedObjectsTable'; export const ASSC_OBJ_TABLE_ACC_COLUMN_NAME = 'accelerations'; -export const ASSC_OBJ_TABLE_SEARCH_HINT = - 'database:database_1 database: database_2 accelerations:skipping_index_1'; +export const ASSC_OBJ_TABLE_SEARCH_HINT = 'accelerations:skipping_index_1'; export const ASSC_OBJ_PANEL_TITLE = 'Associated objects'; diff --git a/public/plugin.tsx b/public/plugin.tsx index eb2cc4cf78..a9cb8786dd 100644 --- a/public/plugin.tsx +++ b/public/plugin.tsx @@ -48,7 +48,7 @@ import { observabilityTracesTitle, } from '../common/constants/shared'; import { QueryManager } from '../common/query_manager'; -import { AssociatedObject, CachedAcceleration } from '../common/types/data_connections'; +import { CachedAcceleration } from '../common/types/data_connections'; import { VISUALIZATION_SAVED_OBJECT } from '../common/types/observability_saved_object_attributes'; import { setOSDHttp, @@ -118,14 +118,16 @@ export const [ export const [ getRenderAssociatedObjectsDetailsFlyout, setRenderAssociatedObjectsDetailsFlyout, -] = createGetterSetter<({ tableDetail }: { tableDetail: AssociatedObject }) => void>( +] = createGetterSetter<({ tableDetail, datasourceName }: AssociatedObjectsFlyoutProps) => void>( 'renderAssociatedObjectsDetailsFlyout' ); export const [ getRenderCreateAccelerationFlyout, setRenderCreateAccelerationFlyout, -] = createGetterSetter<(dataSource: string) => void>('renderCreateAccelerationFlyout'); +] = createGetterSetter<(dataSource: string, databaseName?: string, tableName?: string) => void>( + 'renderCreateAccelerationFlyout' +); export class ObservabilityPlugin implements @@ -424,11 +426,15 @@ export class ObservabilityPlugin }; setRenderAccelerationDetailsFlyout(renderAccelerationDetailsFlyout); - const renderAssociatedObjectsDetailsFlyout = (tableDetail: AssociatedObjectsFlyoutProps) => { + const renderAssociatedObjectsDetailsFlyout = ({ + tableDetail, + datasourceName, + }: AssociatedObjectsFlyoutProps) => { const associatedObjectsDetailsFlyout = core.overlays.openFlyout( toMountPoint( associatedObjectsDetailsFlyout.close()} /> ) @@ -436,12 +442,18 @@ export class ObservabilityPlugin }; setRenderAssociatedObjectsDetailsFlyout(renderAssociatedObjectsDetailsFlyout); - const renderCreateAccelerationFlyout = (selectedDatasource: string) => { + const renderCreateAccelerationFlyout = ( + selectedDatasource: string, + databaseName?: string, + tableName?: string + ) => { const createAccelerationFlyout = core.overlays.openFlyout( toMountPoint( createAccelerationFlyout.close()} + databaseName={databaseName} + tableName={tableName} /> ) ); diff --git a/test/datasources.ts b/test/datasources.ts index c5319b4ae5..8c37eed562 100644 --- a/test/datasources.ts +++ b/test/datasources.ts @@ -1008,19 +1008,19 @@ export const mockAssociatedObjects: AssociatedObject[] = [ ], columns: [ { - name: 'column1', + fieldName: 'column1', dataType: 'dataType1', }, { - name: 'column2', + fieldName: 'column2', dataType: 'dataType2', }, { - name: 'column3', + fieldName: 'column3', dataType: 'dataType3', }, { - name: 'column4', + fieldName: 'column4', dataType: 'dataType4', }, ],