Skip to content

Commit

Permalink
linking create accelerations flyouts, loading columns
Browse files Browse the repository at this point in the history
Signed-off-by: Sean Li <[email protected]>
  • Loading branch information
sejli committed Mar 18, 2024
1 parent 0e7c2bf commit 87e926e
Show file tree
Hide file tree
Showing 13 changed files with 728 additions and 101 deletions.
4 changes: 2 additions & 2 deletions common/types/data_connections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ export interface AssociatedObject {
name: string;
database: string;
type: string;
accelerations: Acceleration[];
columns?: TableColumn[];
accelerations: CachedAcceleration[];
columns?: CachedColumn[];
}

export type Role = EuiComboBoxOptionOption;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -26,7 +28,9 @@ describe('AssociatedObjectsDetailsFlyout Integration Tests', () => {
});

it('renders acceleration details correctly and triggers flyout on click', () => {
const wrapper = mount(<AssociatedObjectsDetailsFlyout tableDetail={mockTableDetail} />);
const wrapper = mount(
<AssociatedObjectsDetailsFlyout tableDetail={mockTableDetail} datasourceName="flint_s3" />
);
expect(wrapper.find('EuiInMemoryTable').at(0).find('EuiLink').length).toBeGreaterThan(0);

wrapper.find('EuiInMemoryTable').at(0).find('EuiLink').first().simulate('click');
Expand All @@ -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(
<AssociatedObjectsDetailsFlyout tableDetail={mockDetailNoAccelerations} />
<AssociatedObjectsDetailsFlyout
tableDetail={mockDetailNoAccelerations}
datasourceName="flint_s3"
/>
);

expect(wrapper.text()).toContain('You have no accelerations');
Expand All @@ -54,24 +61,28 @@ describe('AssociatedObjectsDetailsFlyout Integration Tests', () => {
});

it('renders schema table correctly with column data', () => {
const wrapper = mount(<AssociatedObjectsDetailsFlyout tableDetail={mockTableDetail} />);
const wrapper = mount(
<AssociatedObjectsDetailsFlyout tableDetail={mockTableDetail} datasourceName="flint_s3" />
);

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(<AssociatedObjectsDetailsFlyout tableDetail={mockTableDetail} />);
const wrapper = mount(
<AssociatedObjectsDetailsFlyout tableDetail={mockTableDetail} datasourceName="flint_s3" />
);

await act(async () => {
// Wait a tick for async updates
await new Promise((resolve) => setTimeout(resolve, 0));
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 (
<>
<EuiButton onClick={() => console.log('clicked on create accelerations button')} fill>
<EuiButton onClick={() => renderCreateAccelerationFlyout(dataSourceName)} fill>
Create acceleration
</EuiButton>
</>
Expand Down Expand Up @@ -202,7 +203,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 (
<EuiLink
onClick={() => {
Expand Down Expand Up @@ -297,6 +298,7 @@ export const AccelerationTable = ({
};

const renderAccelerationDetailsFlyout = getRenderAccelerationDetailsFlyout();
const renderCreateAccelerationFlyout = getRenderCreateAccelerationFlyout();

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,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, '_')
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import React, { useEffect, useState } from 'react';
import {
EuiFlyoutBody,
EuiFlyoutHeader,
Expand All @@ -24,26 +24,43 @@ 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,
onDiscoverButtonClick,
} 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 { 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;
}

export const AssociatedObjectsDetailsFlyout = ({ tableDetail }: AssociatedObjectsFlyoutProps) => {
export const AssociatedObjectsDetailsFlyout = ({
tableDetail,
datasourceName,
}: AssociatedObjectsFlyoutProps) => {
const { loadStatus, startLoading } = useLoadTableColumnsToCache();
const [tableColumns, setTableColumns] = useState<CachedColumn[] | undefined>([]);
const [schemaData, setSchemaData] = useState<any>([]);

const DiscoverButton = () => {
// TODO: display button if can be sent to discover
return (
Expand All @@ -55,20 +72,16 @@ export const AssociatedObjectsDetailsFlyout = ({ tableDetail }: AssociatedObject

const AccelerateButton = () => {
return (
<EuiButtonEmpty onClick={onAccelerateButtonClick}>
<EuiButtonEmpty
onClick={() =>
renderCreateAccelerationFlyout(datasourceName, tableDetail.database, tableDetail.name)
}
>
<EuiIcon type={'bolt'} size="m" />
</EuiButtonEmpty>
);
};

const DeleteButton = () => {
return (
<EuiButtonEmpty onClick={onDeleteButtonClick}>
<EuiIcon type="trash" size="m" />
</EuiButtonEmpty>
);
};

const DetailComponent = (detailProps: { title: string; description: any }) => {
const { title, description } = detailProps;
return (
Expand Down Expand Up @@ -108,21 +121,27 @@ export const AssociatedObjectsDetailsFlyout = ({ tableDetail }: AssociatedObject
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) => (
<EuiLink onClick={() => renderAccelerationDetailsFlyout(item)}>{name}</EuiLink>
),
render: (_: string, item: CachedAcceleration) => {
const name = getAccelerationName(item, datasourceName);
return (
<EuiLink
onClick={() =>
renderAccelerationDetailsFlyout({
index: name,
acceleration: item,
dataSourceName: datasourceName,
})
}
>
{name}
</EuiLink>
);
},
},
{
field: 'status',
Expand Down Expand Up @@ -155,7 +174,9 @@ export const AssociatedObjectsDetailsFlyout = ({ tableDetail }: AssociatedObject
<EuiButton
color="primary"
fill
onClick={() => window.open('https://example.com', '_blank')}
onClick={() =>
renderCreateAccelerationFlyout(datasourceName, tableDetail.database, tableDetail.name)
}
iconType="popout"
iconSide="left"
>
Expand All @@ -182,6 +203,37 @@ export const AssociatedObjectsDetailsFlyout = ({ tableDetail }: AssociatedObject

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 (
<>
<EuiFlyoutHeader hasBorder>
Expand All @@ -197,9 +249,6 @@ export const AssociatedObjectsDetailsFlyout = ({ tableDetail }: AssociatedObject
<EuiFlexItem grow={false}>
<AccelerateButton />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<DeleteButton />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlyoutHeader>
<EuiFlyoutBody>
Expand All @@ -225,6 +274,7 @@ export const AssociatedObjectsDetailsFlyout = ({ tableDetail }: AssociatedObject
columns={schemaColumns}
pagination={true}
sorting={true}
loading={isCatalogCacheFetching(loadStatus)}
/>
</EuiFlyoutBody>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,17 +264,18 @@ export const AssociatedObjectsTab: React.FC<AssociatedObjectsTabProps> = (props)
name: table.name,
database: selectedDatabase,
type: 'table',
// Temporary dummy array
accelerations: [],
accelerations: cachedAccelerations.filter(
(acceleration) => acceleration.table === table.name
),
columns: table.columns,
};
});
const accelerationObjects: AssociatedObject[] = cachedAccelerations
.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)!
.label,
Expand Down
Loading

0 comments on commit 87e926e

Please sign in to comment.