diff --git a/common/constants/shared.ts b/common/constants/shared.ts
index 892fa9fc00..73104419eb 100644
--- a/common/constants/shared.ts
+++ b/common/constants/shared.ts
@@ -71,6 +71,7 @@ export const observabilityDataConnectionsTitle = 'Data sources';
export const observabilityDataConnectionsPluginOrder = 9030;
export const queryWorkbenchPluginID = 'opensearch-query-workbench';
+export const queryWorkbenchPluginCheck = 'plugin:queryWorkbenchDashboards';
// Shared Constants
export const SQL_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/search-plugins/sql/index/';
diff --git a/common/types/data_connections.ts b/common/types/data_connections.ts
index d93ba8bf23..b5f2a4ec88 100644
--- a/common/types/data_connections.ts
+++ b/common/types/data_connections.ts
@@ -4,6 +4,7 @@
*/
import { EuiComboBoxOptionOption } from '@elastic/eui';
+import { DirectQueryLoadingStatus } from './explorer';
export type AccelerationStatus = 'ACTIVE' | 'INACTIVE';
@@ -233,3 +234,9 @@ export interface CreateAccelerationForm {
refreshIntervalOptions: RefreshIntervalType;
formErrors: FormErrorsType;
}
+
+export interface LoadCachehookOutput {
+ loadStatus: DirectQueryLoadingStatus;
+ startLoading: (dataSourceName: string, databaseName?: string, tableName?: string) => void;
+ stopLoading: () => void;
+}
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/__snapshots__/create_acceleration.test.tsx.snap b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/__snapshots__/create_acceleration.test.tsx.snap
index 15533e866c..9a00777900 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/__snapshots__/create_acceleration.test.tsx.snap
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/__snapshots__/create_acceleration.test.tsx.snap
@@ -814,7 +814,7 @@ Array [
- No items found
+ Please add fields
@@ -824,31 +824,57 @@ Array [
-
+
+
+ Add fields
+
+
+
+
+
+
+
+
@@ -1188,36 +1214,7 @@ Array [
-
-
+ />
@@ -1713,6 +1712,7 @@ Array [
@@ -2270,7 +2271,7 @@ Array [
- No items found
+ Please add fields
@@ -2280,57 +2281,93 @@ Array [
,
-
+
+
+ Add fields
+
+
+
+
+
+
+
+
-
+ ,
+ "",
+ ]
,
],
@@ -2691,43 +2728,7 @@ Array [
-
-
+ />
+ Promise.resolve({
+ json: () =>
+ Promise.resolve({
+ status: {
+ statuses: [{ id: queryWorkbenchPluginCheck }],
+ },
+ }),
+ })
+);
+
describe('Create acceleration flyout components', () => {
configure({ adapter: new Adapter() });
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/utils.test.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/utils.test.tsx
index f579cc8d2d..f60b782331 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/utils.test.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/__tests__/utils.test.tsx
@@ -109,13 +109,13 @@ describe('validateReplicaCount', () => {
describe('validateRefreshInterval', () => {
it('should return an array with an error message when refreshType is "interval" and refreshWindow is less than 1', () => {
- expect(validateRefreshInterval('interval', 0)).toEqual([
+ expect(validateRefreshInterval('autoInterval', 0)).toEqual([
'refresh window should be greater than 0',
]);
- expect(validateRefreshInterval('interval', -1)).toEqual([
+ expect(validateRefreshInterval('autoInterval', -1)).toEqual([
'refresh window should be greater than 0',
]);
- expect(validateRefreshInterval('interval', -10)).toEqual([
+ expect(validateRefreshInterval('autoInterval', -10)).toEqual([
'refresh window should be greater than 0',
]);
});
@@ -123,8 +123,10 @@ describe('validateRefreshInterval', () => {
it('should return an empty array when refreshType is not "interval" or when refreshWindow is greater than or equal to 1', () => {
expect(validateRefreshInterval('auto', 0)).toEqual([]);
expect(validateRefreshInterval('auto', 1)).toEqual([]);
- expect(validateRefreshInterval('interval', 1)).toEqual([]);
- expect(validateRefreshInterval('auto', 5)).toEqual([]);
+ expect(validateRefreshInterval('autoInterval', 1)).toEqual([]);
+ expect(validateRefreshInterval('autoInterval', 5)).toEqual([]);
+ expect(validateRefreshInterval('manual', 0)).toEqual([]);
+ expect(validateRefreshInterval('manualIncrement', 0)).toEqual([]);
});
});
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/create_acceleration.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/create_acceleration.tsx
index dd8ca4caf9..b9f1aa25ee 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/create_acceleration.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/create/create_acceleration.tsx
@@ -97,7 +97,11 @@ export const CreateAcceleration = ({
},
});
const [tableFieldsLoading, setTableFieldsLoading] = useState(false);
- const { loadStatus, startLoading } = useLoadTableColumnsToCache();
+ const {
+ loadStatus,
+ startLoading,
+ stopLoading: stopLoadingTableFields,
+ } = useLoadTableColumnsToCache();
const loadColumnsToAccelerationForm = (cachedTable: CachedTable) => {
const idPrefix = htmlIdGenerator()();
@@ -117,6 +121,7 @@ export const CreateAcceleration = ({
...accelerationFormData,
dataTableFields: [],
});
+ stopLoadingTableFields();
if (dataTable !== '') {
setTableFieldsLoading(true);
const cachedTable = CatalogCacheManager.getTable(dataSource, database, dataTable);
@@ -179,6 +184,7 @@ export const CreateAcceleration = ({
setAccelerationFormData={setAccelerationFormData}
selectedDatasource={selectedDatasource}
dataSourcesPreselected={dataSourcesPreselected}
+ tableFieldsLoading={tableFieldsLoading}
/>
{
- return refreshType !== 'auto' && refreshType !== 'manual' && refreshWindow < 1
+ return refreshType === 'autoInterval' && refreshWindow < 1
? ['refresh window should be greater than 0']
: [];
};
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/__snapshots__/preview_sql_defintion.test.tsx.snap b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/__snapshots__/preview_sql_defintion.test.tsx.snap
index afecf2109d..802f07f9e8 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/__snapshots__/preview_sql_defintion.test.tsx.snap
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/__snapshots__/preview_sql_defintion.test.tsx.snap
@@ -90,43 +90,7 @@ exports[`Preview SQL acceleration components renders Preview SQL settings with d
-
-
+ />
-
-
+ />
-
-
+ />
-
-
+ />
@@ -261,6 +263,7 @@ Array [
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/preview_sql_defintion.test.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/preview_sql_defintion.test.tsx
index 1ba0213678..ce265635b0 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/preview_sql_defintion.test.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/preview_sql_defintion.test.tsx
@@ -8,6 +8,7 @@ import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import toJson from 'enzyme-to-json';
import React from 'react';
+import { queryWorkbenchPluginCheck } from '../../../../../../../../../common/constants/shared';
import { CreateAccelerationForm } from '../../../../../../../../../common/types/data_connections';
import {
coveringIndexBuilderMock1,
@@ -16,6 +17,18 @@ import {
} from '../../../../../../../../../test/accelerations';
import { PreviewSQLDefinition } from '../preview_sql_defintion';
+// @ts-ignore
+global.fetch = jest.fn(() =>
+ Promise.resolve({
+ json: () =>
+ Promise.resolve({
+ status: {
+ statuses: [{ id: queryWorkbenchPluginCheck }],
+ },
+ }),
+ })
+);
+
describe('Preview SQL acceleration components', () => {
configure({ adapter: new Adapter() });
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/source_selector.test.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/source_selector.test.tsx
index 5a96679119..040b1a4b69 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/source_selector.test.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/__tests__/source_selector.test.tsx
@@ -35,6 +35,7 @@ describe('Source selector components', () => {
accelerationFormData={accelerationFormData}
setAccelerationFormData={setAccelerationFormData}
dataSourcesPreselected={false}
+ tableFieldsLoading={false}
/>
);
wrapper.update();
@@ -67,6 +68,7 @@ describe('Source selector components', () => {
accelerationFormData={accelerationFormData}
setAccelerationFormData={setAccelerationFormData}
dataSourcesPreselected={true}
+ tableFieldsLoading={false}
/>
);
wrapper.update();
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/preview_sql_defintion.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/preview_sql_defintion.tsx
index 3170df61d8..b0c61b7560 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/preview_sql_defintion.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/preview_sql_defintion.tsx
@@ -13,7 +13,13 @@ import {
EuiText,
} from '@elastic/eui';
import React, { useEffect, useState } from 'react';
+import {
+ queryWorkbenchPluginCheck,
+ queryWorkbenchPluginID,
+} from '../../../../../../../../common/constants/shared';
import { CreateAccelerationForm } from '../../../../../../../../common/types/data_connections';
+import { coreRefs } from '../../../../../../../framework/core_refs';
+import { useToast } from '../../../../../../common/toast';
import { formValidator, hasError } from '../create/utils';
import { accelerationQueryBuilder } from '../visual_editors/query_builder';
@@ -26,14 +32,22 @@ export const PreviewSQLDefinition = ({
accelerationFormData,
setAccelerationFormData,
}: PreviewSQLDefinitionProps) => {
+ const { setToast } = useToast();
const [isPreviewStale, setIsPreviewStale] = useState(false);
const [isPreviewTriggered, setIsPreviewTriggered] = useState(false);
const [sqlCode, setSQLcode] = useState('');
+ const [sqlWorkbenchPLuginExists, setSQLWorkbenchPluginExists] = useState(false);
- const onClickPreview = () => {
+ const checkForErrors = () => {
const errors = formValidator(accelerationFormData);
if (hasError(errors)) {
setAccelerationFormData({ ...accelerationFormData, formErrors: errors });
+ return true;
+ } else return false;
+ };
+
+ const onClickPreview = () => {
+ if (checkForErrors()) {
return;
}
setSQLcode(accelerationQueryBuilder(accelerationFormData));
@@ -41,10 +55,66 @@ export const PreviewSQLDefinition = ({
setIsPreviewTriggered(true);
};
+ const checkIfSQLWorkbenchPluginIsInstalled = () => {
+ fetch('../api/status', {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'osd-xsrf': 'true',
+ 'accept-language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6',
+ pragma: 'no-cache',
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ },
+ method: 'GET',
+ referrerPolicy: 'strict-origin-when-cross-origin',
+ mode: 'cors',
+ credentials: 'include',
+ })
+ .then(function (response) {
+ return response.json();
+ })
+ .then((data) => {
+ for (let i = 0; i < data.status.statuses.length; ++i) {
+ if (data.status.statuses[i].id.includes(queryWorkbenchPluginCheck)) {
+ setSQLWorkbenchPluginExists(true);
+ }
+ }
+ })
+ .catch((error) => {
+ setToast('Error checking Query Workbench Plugin Installation status.', 'danger');
+ console.error(error);
+ });
+ };
+
+ const openInWorkbench = () => {
+ if (!checkForErrors()) {
+ coreRefs?.application!.navigateToApp(queryWorkbenchPluginID, {
+ path: `#/${accelerationFormData.dataSource}`,
+ state: {
+ language: 'sql',
+ queryToRun: accelerationQueryBuilder(accelerationFormData),
+ },
+ });
+ }
+ };
+
+ const queryWorkbenchButton = sqlWorkbenchPLuginExists ? (
+
+ Open in Query Workbench
+
+ ) : (
+ <>>
+ );
+
useEffect(() => {
setIsPreviewStale(true);
}, [accelerationFormData]);
+ useEffect(() => {
+ checkIfSQLWorkbenchPluginIsInstalled();
+ }, []);
+
return (
<>
)}
-
-
- Open in Query Workbench
-
-
+ {queryWorkbenchButton}
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_databases.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_databases.tsx
index c867be1ffc..635cf6976e 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_databases.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_databases.tsx
@@ -11,11 +11,27 @@ import { useLoadDatabasesToCache } from '../../../../../../../../framework/catal
interface SelectorLoadDatabasesProps {
dataSourceName: string;
loadDatabases: () => void;
+ loadingComboBoxes: {
+ dataSource: boolean;
+ database: boolean;
+ dataTable: boolean;
+ };
+ setLoadingComboBoxes: React.Dispatch<
+ React.SetStateAction<{
+ dataSource: boolean;
+ database: boolean;
+ dataTable: boolean;
+ }>
+ >;
+ tableFieldsLoading: boolean;
}
export const SelectorLoadDatabases = ({
dataSourceName,
loadDatabases,
+ loadingComboBoxes,
+ setLoadingComboBoxes,
+ tableFieldsLoading,
}: SelectorLoadDatabasesProps) => {
const [isLoading, setIsLoading] = useState(false);
const {
@@ -42,6 +58,10 @@ export const SelectorLoadDatabases = ({
}
}, [loadDatabasesStatus]);
+ useEffect(() => {
+ setLoadingComboBoxes({ ...loadingComboBoxes, database: isLoading });
+ }, [isLoading]);
+
return (
<>
{isLoading ? (
@@ -52,6 +72,9 @@ export const SelectorLoadDatabases = ({
size="m"
display="base"
onClick={onClickRefreshDatabases}
+ isDisabled={
+ loadingComboBoxes.database || loadingComboBoxes.dataTable || tableFieldsLoading
+ }
/>
)}
>
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_objects.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_objects.tsx
index f56ad879f0..d687ef6ede 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_objects.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/selector_helpers/load_objects.tsx
@@ -16,12 +16,28 @@ interface SelectorLoadDatabasesProps {
dataSourceName: string;
databaseName: string;
loadTables: () => void;
+ loadingComboBoxes: {
+ dataSource: boolean;
+ database: boolean;
+ dataTable: boolean;
+ };
+ setLoadingComboBoxes: React.Dispatch<
+ React.SetStateAction<{
+ dataSource: boolean;
+ database: boolean;
+ dataTable: boolean;
+ }>
+ >;
+ tableFieldsLoading: boolean;
}
export const SelectorLoadObjects = ({
dataSourceName,
databaseName,
loadTables,
+ loadingComboBoxes,
+ setLoadingComboBoxes,
+ tableFieldsLoading,
}: SelectorLoadDatabasesProps) => {
const { setToast } = useToast();
const [isLoading, setIsLoading] = useState({
@@ -77,6 +93,10 @@ export const SelectorLoadObjects = ({
}
}, [loadAccelerationsStatus]);
+ useEffect(() => {
+ setLoadingComboBoxes({ ...loadingComboBoxes, dataTable: isEitherLoading });
+ }, [isEitherLoading]);
+
return (
<>
{isEitherLoading ? (
@@ -87,6 +107,9 @@ export const SelectorLoadObjects = ({
size="m"
display="base"
onClick={onClickRefreshDatabases}
+ isDisabled={
+ loadingComboBoxes.database || loadingComboBoxes.dataTable || tableFieldsLoading
+ }
/>
)}
>
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/source_selector.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/source_selector.tsx
index 29866ba0df..f1dac3eac5 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/source_selector.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/selectors/source_selector.tsx
@@ -35,6 +35,7 @@ interface AccelerationDataSourceSelectorProps {
setAccelerationFormData: React.Dispatch>;
selectedDatasource: string;
dataSourcesPreselected: boolean;
+ tableFieldsLoading: boolean;
}
export const AccelerationDataSourceSelector = ({
@@ -43,6 +44,7 @@ export const AccelerationDataSourceSelector = ({
setAccelerationFormData,
selectedDatasource,
dataSourcesPreselected,
+ tableFieldsLoading,
}: AccelerationDataSourceSelectorProps) => {
const { setToast } = useToast();
const [databases, setDatabases] = useState>>([]);
@@ -89,7 +91,6 @@ export const AccelerationDataSourceSelector = ({
};
const loadDatabases = () => {
- setLoadingComboBoxes({ ...loadingComboBoxes, database: true });
const dsCache = CatalogCacheManager.getOrCreateDataSource(accelerationFormData.dataSource);
if (dsCache.status === CachedDataSourceStatus.Updated && dsCache.databases.length > 0) {
@@ -106,11 +107,9 @@ export const AccelerationDataSourceSelector = ({
setTables([]);
setSelectedTable([]);
setAccelerationFormData({ ...accelerationFormData, database: '', dataTable: '' });
- setLoadingComboBoxes({ ...loadingComboBoxes, database: false });
};
const loadTables = () => {
- setLoadingComboBoxes({ ...loadingComboBoxes, dataTable: true });
if (selectedDatabase.length > 0) {
const dbCache = CatalogCacheManager.getDatabase(
accelerationFormData.dataSource,
@@ -127,7 +126,6 @@ export const AccelerationDataSourceSelector = ({
}
setSelectedTable([]);
setAccelerationFormData({ ...accelerationFormData, dataTable: '' });
- setLoadingComboBoxes({ ...loadingComboBoxes, dataTable: false });
}
};
@@ -212,20 +210,29 @@ export const AccelerationDataSourceSelector = ({
}}
isClearable={false}
isInvalid={hasError(accelerationFormData.formErrors, 'databaseError')}
- isLoading={loadingComboBoxes.database}
+ isDisabled={
+ loadingComboBoxes.database || loadingComboBoxes.dataTable || tableFieldsLoading
+ }
/>
@@ -251,7 +258,9 @@ export const AccelerationDataSourceSelector = ({
}}
isClearable={false}
isInvalid={hasError(accelerationFormData.formErrors, 'dataTableError')}
- isLoading={loadingComboBoxes.dataTable}
+ isDisabled={
+ loadingComboBoxes.database || loadingComboBoxes.dataTable || tableFieldsLoading
+ }
/>
@@ -259,6 +268,9 @@ export const AccelerationDataSourceSelector = ({
dataSourceName={accelerationFormData.dataSource}
databaseName={accelerationFormData.database}
loadTables={loadTables}
+ loadingComboBoxes={loadingComboBoxes}
+ setLoadingComboBoxes={setLoadingComboBoxes}
+ tableFieldsLoading={tableFieldsLoading}
/>
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/__tests__/__snapshots__/query_visual_editor.test.tsx.snap b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/__tests__/__snapshots__/query_visual_editor.test.tsx.snap
index b75e89152d..85e73b484b 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/__tests__/__snapshots__/query_visual_editor.test.tsx.snap
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/__tests__/__snapshots__/query_visual_editor.test.tsx.snap
@@ -241,7 +241,7 @@ Array [
- No items found
+ Please add fields
@@ -251,57 +251,93 @@ Array [
,
-
+
+
+ Add fields
+
+
+
+
+
+
+
+
-
+ ,
+ "",
+ ]
,
],
@@ -601,6 +637,7 @@ Array [
>
|
|
|
|
|
|
|
,
-
+
+
+ Add fields
+
+
+
+
+
+
+
+
-
+ ,
+ "",
+ ]
,
],
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/__snapshots__/generate_fields.test.tsx.snap b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/__snapshots__/generate_fields.test.tsx.snap
new file mode 100644
index 0000000000..decdb88aaa
--- /dev/null
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/__snapshots__/generate_fields.test.tsx.snap
@@ -0,0 +1,28 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Generate fields in skipping index Generate fields in skipping index with default options 1`] = `
+Array [
+ ,
+ "",
+]
+`;
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/__snapshots__/skipping_index_builder.test.tsx.snap b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/__snapshots__/skipping_index_builder.test.tsx.snap
index a00e12b818..d9b73eabbf 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/__snapshots__/skipping_index_builder.test.tsx.snap
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/__snapshots__/skipping_index_builder.test.tsx.snap
@@ -151,7 +151,7 @@ Array [
- No items found
+ Please add fields
|
@@ -161,57 +161,93 @@ Array [
,
-
+
+
+ Add fields
+
+
+
+
+
+
+
+
-
+ ,
+ "",
+ ]
,
]
@@ -355,6 +391,7 @@ Array [
>
|
|
|
|
|
|
|
,
-
+
+
+ Add fields
+
+
+
+
+
+
+
+
-
+ ,
+ "",
+ ]
,
]
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/generate_fields.test.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/generate_fields.test.tsx
new file mode 100644
index 0000000000..7a5b9ccb1f
--- /dev/null
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/__tests__/generate_fields.test.tsx
@@ -0,0 +1,43 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { waitFor } from '@testing-library/dom';
+import { configure, mount } from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+import toJson from 'enzyme-to-json';
+import React from 'react';
+import { createAccelerationEmptyDataMock } from '../../../../../../../../../../test/accelerations';
+import { GenerateFields } from '../generate_fields';
+
+describe('Generate fields in skipping index', () => {
+ configure({ adapter: new Adapter() });
+
+ it('Generate fields in skipping index with default options', async () => {
+ const accelerationFormData = createAccelerationEmptyDataMock;
+ const setAccelerationFormData = jest.fn();
+ const wrapper = mount(
+
+ );
+ wrapper.update();
+ await waitFor(() => {
+ expect(
+ toJson(wrapper, {
+ noKey: false,
+ mode: 'deep',
+ })
+ ).toMatchSnapshot();
+ });
+ });
+});
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/generate_fields.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/generate_fields.tsx
new file mode 100644
index 0000000000..5eda5b73aa
--- /dev/null
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/generate_fields.tsx
@@ -0,0 +1,125 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { EuiButton, EuiConfirmModal } from '@elastic/eui';
+import producer from 'immer';
+import React, { useEffect, useState } from 'react';
+import {
+ CreateAccelerationForm,
+ SkippingIndexRowType,
+} from '../../../../../../../../../common/types/data_connections';
+import {
+ DirectQueryLoadingStatus,
+ DirectQueryRequest,
+} from '../../../../../../../../../common/types/explorer';
+import {
+ addBackticksIfNeeded,
+ combineSchemaAndDatarows,
+} from '../../../../../../../../../common/utils/shared';
+import { useDirectQuery } from '../../../../../../../../framework/datasources/direct_query_hook';
+import { validateSkippingIndexData } from '../../create/utils';
+
+interface GenerateFieldsProps {
+ accelerationFormData: CreateAccelerationForm;
+ setAccelerationFormData: React.Dispatch>;
+ isSkippingtableLoading: boolean;
+ setIsSkippingtableLoading: React.Dispatch;
+}
+
+export const GenerateFields = ({
+ accelerationFormData,
+ setAccelerationFormData,
+ isSkippingtableLoading,
+ setIsSkippingtableLoading,
+}: GenerateFieldsProps) => {
+ const [isGenerateRun, setIsGenerateRun] = useState(false);
+ const { loadStatus, startLoading, stopLoading: _stopLoading, pollingResult } = useDirectQuery();
+ const [replaceDefinitionModal, setReplaceDefinitionModal] = useState(<>>);
+
+ const mapToDataTableFields = (fieldName: string) => {
+ return accelerationFormData.dataTableFields.find((field) => field.fieldName === fieldName);
+ };
+
+ const loadSkippingIndexDefinition = () => {
+ const combinedData = combineSchemaAndDatarows(pollingResult.schema, pollingResult.datarows);
+ const skippingIndexRows = combinedData.map((field: any) => {
+ return {
+ ...mapToDataTableFields(field.column_name),
+ accelerationMethod: field.skipping_type.split(' ')[0],
+ } as SkippingIndexRowType;
+ });
+ setAccelerationFormData(
+ producer((accData) => {
+ accData.skippingIndexQueryData = skippingIndexRows;
+ accData.formErrors.skippingIndexError = validateSkippingIndexData(
+ accData.accelerationIndexType,
+ skippingIndexRows
+ );
+ })
+ );
+ };
+
+ useEffect(() => {
+ const status = loadStatus.toLowerCase();
+ if (status === DirectQueryLoadingStatus.SUCCESS) {
+ loadSkippingIndexDefinition();
+ setIsSkippingtableLoading(false);
+ } else if (
+ status === DirectQueryLoadingStatus.FAILED ||
+ status === DirectQueryLoadingStatus.CANCELED
+ ) {
+ setIsSkippingtableLoading(false);
+ }
+ }, [loadStatus]);
+
+ const runGeneration = () => {
+ const requestPayload: DirectQueryRequest = {
+ lang: 'sql',
+ query: `ANALYZE SKIPPING INDEX ON ${addBackticksIfNeeded(
+ accelerationFormData.dataSource
+ )}.${addBackticksIfNeeded(accelerationFormData.database)}.${addBackticksIfNeeded(
+ accelerationFormData.dataTable
+ )}`,
+ datasource: accelerationFormData.dataSource,
+ };
+ startLoading(requestPayload);
+ setIsSkippingtableLoading(true);
+ setIsGenerateRun(true);
+ setReplaceDefinitionModal(<>>);
+ };
+
+ const replaceModalComponent = (
+ setReplaceDefinitionModal(<>>)}
+ onConfirm={runGeneration}
+ cancelButtonText="Cancel"
+ confirmButtonText="Replace"
+ defaultFocusedButton="confirm"
+ >
+
+ Existing definitions will be removed and replaced with auto-generated definitions. Do you
+ want to continue?
+
+
+ );
+
+ const onClickGenerate = () => {
+ if (accelerationFormData.skippingIndexQueryData.length > 0) {
+ setReplaceDefinitionModal(replaceModalComponent);
+ } else {
+ runGeneration();
+ }
+ };
+
+ return (
+ <>
+
+ {isGenerateRun ? 'Regenerate' : 'Generate'}
+
+ {replaceDefinitionModal}
+ >
+ );
+};
diff --git a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/skipping_index_builder.tsx b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/skipping_index_builder.tsx
index ae2a03e14f..1669d05c81 100644
--- a/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/skipping_index_builder.tsx
+++ b/public/components/datasources/components/manage/accelerations/create_accelerations_flyout/visual_editors/skipping_index/skipping_index_builder.tsx
@@ -13,7 +13,6 @@ import {
EuiSpacer,
EuiText,
} from '@elastic/eui';
-import producer from 'immer';
import React, { useEffect, useState } from 'react';
import { SKIPPING_INDEX_ACCELERATION_METHODS } from '../../../../../../../../../common/constants/data_sources';
import {
@@ -21,9 +20,9 @@ import {
SkippingIndexAccMethodType,
SkippingIndexRowType,
} from '../../../../../../../../../common/types/data_connections';
-import { validateSkippingIndexData } from '../../create/utils';
import { AddFieldsModal } from './add_fields_modal';
import { DeleteFieldsModal } from './delete_fields_modal';
+import { GenerateFields } from './generate_fields';
interface SkippingIndexBuilderProps {
accelerationFormData: CreateAccelerationForm;
@@ -40,6 +39,7 @@ export const SkippingIndexBuilder = ({
const [isAddModalVisible, setIsAddModalVisible] = useState(false);
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
+ const [isSkippingtableLoading, setIsSkippingtableLoading] = useState(false);
let modal;
@@ -86,12 +86,14 @@ export const SkippingIndexBuilder = ({
name: 'Field name',
sortable: true,
truncateText: true,
+ readOnly: isSkippingtableLoading,
},
{
field: 'dataType',
name: 'Datatype',
sortable: true,
truncateText: true,
+ readOnly: isSkippingtableLoading,
},
{
name: 'Acceleration method',
@@ -104,9 +106,11 @@ export const SkippingIndexBuilder = ({
aria-label="Use aria labels when no actual label is in use"
/>
),
+ readOnly: isSkippingtableLoading,
},
{
name: 'Delete',
+ readOnly: isSkippingtableLoading,
render: (item: SkippingIndexRowType) => {
return (
{
- if (accelerationFormData.dataTableFields.length > 0) {
- const tableRows: SkippingIndexRowType[] = [
- {
- ...accelerationFormData.dataTableFields[0],
- accelerationMethod: 'PARTITION',
- },
- ];
- setAccelerationFormData(
- producer((accData) => {
- accData.skippingIndexQueryData = tableRows;
- accData.formErrors.skippingIndexError = validateSkippingIndexData(
- accData.accelerationIndexType,
- tableRows
- );
- })
- );
- } else {
- setAccelerationFormData({ ...accelerationFormData, skippingIndexQueryData: [] });
- }
- }, [accelerationFormData.dataTableFields]);
-
useEffect(() => {
setTotalItemCount(accelerationFormData.skippingIndexQueryData.length);
}, [accelerationFormData.skippingIndexQueryData]);
@@ -176,17 +158,42 @@ export const SkippingIndexBuilder = ({
onChange={({ page }) => onTableChange(page)}
hasActions={true}
error={accelerationFormData.formErrors.skippingIndexError.join('')}
+ loading={isSkippingtableLoading}
+ noItemsMessage={
+ isSkippingtableLoading
+ ? 'Auto-generating skipping index definition.'
+ : 'Please add fields'
+ }
/>
-
-
- setIsAddModalVisible(true)}>
- Add fields
-
+
+
+
+
+ setIsAddModalVisible(true)}
+ isDisabled={isSkippingtableLoading}
+ >
+ Add fields
+
+
+
+ setIsDeleteModalVisible(true)}
+ isDisabled={isSkippingtableLoading}
+ color="danger"
+ >
+ Bulk delete
+
+
+
- setIsDeleteModalVisible(true)} color="danger">
- Bulk delete
-
+
{modal}
diff --git a/public/framework/core_refs.ts b/public/framework/core_refs.ts
index 275158258a..ed378ae1da 100644
--- a/public/framework/core_refs.ts
+++ b/public/framework/core_refs.ts
@@ -10,6 +10,7 @@ import {
CoreStart,
HttpStart,
IToasts,
+ OverlayStart,
SavedObjectsClientContract,
} from '../../../../src/core/public';
import { DashboardStart } from '../../../../src/plugins/dashboard/public';
@@ -30,6 +31,7 @@ class CoreRefs {
public summarizeEnabled?: boolean;
public dashboard?: DashboardStart;
public dashboardProviders?: unknown;
+ public overlays?: OverlayStart;
private constructor() {
// ...
}
diff --git a/public/framework/datasources/direct_query_hook.tsx b/public/framework/datasources/direct_query_hook.tsx
index f44c04d8f4..f4776385e8 100644
--- a/public/framework/datasources/direct_query_hook.tsx
+++ b/public/framework/datasources/direct_query_hook.tsx
@@ -88,5 +88,5 @@ export const useDirectQuery = () => {
}
}, [pollingResult, pollingError]);
- return { loadStatus, startLoading, stopLoading };
+ return { loadStatus, startLoading, stopLoading, pollingResult };
};
diff --git a/public/plugin.tsx b/public/plugin.tsx
index 2b8a64f327..6b2b65ccfa 100644
--- a/public/plugin.tsx
+++ b/public/plugin.tsx
@@ -73,6 +73,13 @@ import {
} from './embeddable/observability_embeddable';
import { ObservabilityEmbeddableFactoryDefinition } from './embeddable/observability_embeddable_factory';
import { catalogCacheInterceptError } from './framework/catalog_cache/cache_intercept';
+import {
+ useLoadAccelerationsToCache,
+ useLoadDatabasesToCache,
+ useLoadTableColumnsToCache,
+ useLoadTablesToCache,
+} from './framework/catalog_cache/cache_loader';
+import { CatalogCacheManager } from './framework/catalog_cache/cache_manager';
import { coreRefs } from './framework/core_refs';
import { DataSourcePluggable } from './framework/datasource_pluggables/datasource_pluggable';
import { S3DataSource } from './framework/datasources/s3_datasource';
@@ -371,6 +378,7 @@ export class ObservabilityPlugin
coreRefs.dashboard = startDeps.dashboard;
coreRefs.queryAssistEnabled = this.config.query_assist.enabled;
coreRefs.summarizeEnabled = this.config.summarize.enabled;
+ coreRefs.overlays = core.overlays;
const { dataSourceService, dataSourceFactory } = startDeps.data.dataSources;
@@ -445,11 +453,21 @@ export class ObservabilityPlugin
};
setRenderCreateAccelerationFlyout(renderCreateAccelerationFlyout);
+ const CatalogCacheManagerInstance = CatalogCacheManager;
+ const useLoadDatabasesToCacheHook = useLoadDatabasesToCache;
+ const useLoadTablesToCacheHook = useLoadTablesToCache;
+ const useLoadTableColumnsToCacheHook = useLoadTableColumnsToCache;
+ const useLoadAccelerationsToCacheHook = useLoadAccelerationsToCache;
// Export so other plugins can use this flyout
return {
renderAccelerationDetailsFlyout,
renderAssociatedObjectsDetailsFlyout,
renderCreateAccelerationFlyout,
+ CatalogCacheManagerInstance,
+ useLoadDatabasesToCacheHook,
+ useLoadTablesToCacheHook,
+ useLoadTableColumnsToCacheHook,
+ useLoadAccelerationsToCacheHook,
};
}
diff --git a/public/types.ts b/public/types.ts
index fac6d463d7..e63805b594 100644
--- a/public/types.ts
+++ b/public/types.ts
@@ -11,7 +11,12 @@ import { ManagementOverViewPluginSetup } from '../../../src/plugins/management_o
import { NavigationPublicPluginStart } from '../../../src/plugins/navigation/public';
import { UiActionsStart } from '../../../src/plugins/ui_actions/public';
import { VisualizationsSetup } from '../../../src/plugins/visualizations/public';
-import { AssociatedObject, CachedAcceleration } from '../common/types/data_connections';
+import {
+ AssociatedObject,
+ CachedAcceleration,
+ LoadCachehookOutput,
+} from '../common/types/data_connections';
+import { CatalogCacheManager } from './framework/catalog_cache/cache_manager';
import { AssistantSetup } from './types';
export interface AppPluginStartDependencies {
@@ -41,13 +46,26 @@ export interface ObservabilityStart {
datasourceName: string,
handleRefresh?: () => void
) => void;
- renderAssociatedObjectsDetailsFlyout: (
- tableDetail: AssociatedObject,
- datasourceName: string
+ renderAssociatedObjectsDetailsFlyout: ({
+ tableDetail,
+ }: {
+ tableDetail: AssociatedObject;
+ }) => void;
+ renderCreateAccelerationFlyout: (
+ dataSource: string,
+ databaseName?: string,
+ tableName?: string
) => void;
- renderCreateAccelerationFlyout: (selectedDatasource: string) => void;
+ CatalogCacheManagerInstance: typeof CatalogCacheManager;
+ useLoadDatabasesToCacheHook: () => LoadCachehookOutput;
+ useLoadTablesToCacheHook: () => LoadCachehookOutput;
+ useLoadTableColumnsToCacheHook: () => LoadCachehookOutput;
+ useLoadAccelerationsToCacheHook: () => LoadCachehookOutput;
}
+export type CatalogCacheManagerType = typeof CatalogCacheManager;
+export type LoadCachehookOutputType = LoadCachehookOutput;
+
/**
* Introduce a compile dependency on dashboards-assistant
* as observerability need some types from the plugin.
|