Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
export const PLUGIN_ID = 'queryWorkbenchDashboards';
export const PLUGIN_NAME = 'Query Workbench';
export const OPENSEARCH_ACC_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest';
export const ACC_INDEX_TYPE_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest';
Comment thread
ps48 marked this conversation as resolved.

export const ACCELERATION_INDEX_TYPES = [
{ label: 'Skipping Index', value: 'skipping' },
Expand All @@ -14,9 +15,33 @@ export const ACCELERATION_INDEX_TYPES = [
];

export const ACCELERATION_AGGREGRATION_FUNCTIONS = [
{ label: 'count', value: 'count' },
{ label: 'sum', value: 'sum' },
{ label: 'avg', value: 'avg' },
{ label: 'max', value: 'max' },
{ label: 'min', value: 'min' },
{ label: 'count' },
{ label: 'sum' },
{ label: 'avg' },
{ label: 'max' },
{ label: 'min' },
];

export const ACCELERATION_TIME_INTERVAL = [
{ text: 'millisecond(s)', value: 'millisecond' },
{ text: 'second(s)', value: 'second' },
{ text: 'hour(s)', value: 'hour' },
{ text: 'day(s)', value: 'day' },
{ text: 'week(s)', value: 'week' },
];

export const ACCELERATION_ADD_FIELDS_TEXT = '(add fields here)';

export const ACCELERATION_INDEX_NAME_INFO = `All OpenSearch acceleration indices have a naming format of pattern: \`prefix_<index name>_suffix\`. They share a common prefix structure, which is \`flint_<data source name>_<database name>_<table name>_\`. Additionally, they may have a suffix that varies based on the index type.
##### Skipping Index
- For 'Skipping' indices, a fixed index name 'skipping' is used, and this name cannot be modified by the user. The suffix added to this type is \`_index\`.
- An example of a 'Skipping' index name would be: \`flint_mydatasource_mydb_mytable_skipping_index\`.
##### Covering Index
- 'Covering' indices allow users to specify their index name. The suffix added to this type is \`_index\`.
- For instance, a 'Covering' index name could be: \`flint_mydatasource_mydb_mytable_myindexname_index\`.
##### Materialized View Index
- 'Materialized View' indices also enable users to define their index name, but they do not have a suffix.
- An example of a 'Materialized View' index name might look like: \`flint_mydatasource_mydb_mytable_myindexname\`.
##### Note:
- All user given index names must be in lowercase letters. Cannot begin with underscores or hyphens. Spaces, commas, and characters :, ", *, +, /, \, |, ?, #, >, or < are not allowed.
Comment thread
ps48 marked this conversation as resolved.
Comment thread
ps48 marked this conversation as resolved.
`;
34 changes: 27 additions & 7 deletions common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

export type AggregationFunctionType = 'count' | 'sum' | 'avg' | 'max' | 'min';

export interface MaterializedViewColumn {
id: string;
functionName: 'count' | 'sum' | 'avg' | 'min' | 'max';
functionName: AggregationFunctionType;
Comment thread
ps48 marked this conversation as resolved.
functionParam: string;
fieldAlias?: string;
}
Expand All @@ -23,19 +25,37 @@ export interface DataTableFieldsType {
dataType: string;
}

export interface RefreshIntervalType {
refreshWindow: number;
refreshInterval: string;
}

export type AccelerationIndexType = 'skipping' | 'covering' | 'materialized';

export interface GroupByTumbleType {
timeField: string;
tumbleWindow: number;
tumbleInterval: string;
}

export interface materializedViewQueryType {
columnsValues: MaterializedViewColumn[];
groupByTumbleValue: GroupByTumbleType;
}

export interface CreateAccelerationForm {
dataSource: string;
database: string;
dataTable: string;
dataTableFields: DataTableFieldsType[];
accelerationIndexType: 'skipping' | 'covering' | 'materialized';
queryBuilderType: 'visual' | 'code';
accelerationIndexType: AccelerationIndexType;
skippingIndexQueryData: SkippingIndexRowType[];
coveringIndexQueryData: string;
materializedViewQueryData: string;
coveringIndexQueryData: string[];
materializedViewQueryData: materializedViewQueryType;
accelerationIndexName: string;
accelerationIndexAlias: string;
primaryShardsCount: number;
replicaShardsCount: number;
refreshType: 'interval' | 'auto';
refreshIntervalSeconds: string | undefined;
checkpointLocation: string | undefined;
refreshIntervalOptions: RefreshIntervalType | undefined;
}
50 changes: 34 additions & 16 deletions public/components/acceleration/create/create_acceleration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,26 @@
*/

import {
EuiSpacer,
EuiFlyout,
EuiFlyoutBody,
EuiFlyoutHeader,
EuiFlyoutFooter,
EuiButton,
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiFlyout,
EuiFlyoutBody,
EuiFlyoutFooter,
EuiFlyoutHeader,
EuiSpacer,
} from '@elastic/eui';
import React, { useState } from 'react';
import { CreateAccelerationHeader } from './create_acceleration_header';
import { CautionBannerCallout } from './caution_banner_callout';
import { AccelerationDataSourceSelector } from '../selectors/source_selector';
import { IndexTypeSelector } from '../selectors/index_type_selector';
import { ACCELERATION_TIME_INTERVAL } from '../../../../common/constants';
import { CreateAccelerationForm } from '../../../../common/types/';
import { QueryVisualEditor } from '../visual_editors/query_visual_editor';
import { DefineIndexOptions } from '../selectors/define_index_options';
import { IndexSettingOptions } from '../selectors/index_setting_options';
import { AccelerationDataSourceSelector } from '../selectors/source_selector';
import { accelerationQueryBuilder } from '../visual_editors/query_builder';
import { QueryVisualEditor } from '../visual_editors/query_visual_editor';
import { CautionBannerCallout } from './caution_banner_callout';
import { CreateAccelerationHeader } from './create_acceleration_header';

export interface CreateAccelerationProps {
dataSource: string;
Expand All @@ -37,18 +39,28 @@ export const CreateAcceleration = ({
const [accelerationFormData, setAccelerationFormData] = useState<CreateAccelerationForm>({
dataSource: '',
dataTable: '',
database: '',
dataTableFields: [],
accelerationIndexType: 'skipping',
queryBuilderType: 'visual',
skippingIndexQueryData: [],
coveringIndexQueryData: '',
materializedViewQueryData: '',
coveringIndexQueryData: [],
materializedViewQueryData: {
columnsValues: [],
groupByTumbleValue: {
timeField: '',
tumbleWindow: 0,
tumbleInterval: '',
},
},
accelerationIndexName: '',
accelerationIndexAlias: '',
primaryShardsCount: 5,
replicaShardsCount: 1,
refreshType: 'auto',
refreshIntervalSeconds: undefined,
checkpointLocation: undefined,
refreshIntervalOptions: {
refreshWindow: 1,
refreshInterval: ACCELERATION_TIME_INTERVAL[1].value,
},
});

const copyToEditor = () => {
Expand All @@ -73,7 +85,13 @@ export const CreateAcceleration = ({
accelerationFormData={accelerationFormData}
setAccelerationFormData={setAccelerationFormData}
/>
<IndexTypeSelector
<EuiSpacer size="xxl" />
<IndexSettingOptions
accelerationFormData={accelerationFormData}
setAccelerationFormData={setAccelerationFormData}
/>
<EuiSpacer size="xxl" />
<DefineIndexOptions
accelerationFormData={accelerationFormData}
setAccelerationFormData={setAccelerationFormData}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*/

import {
EuiLink,
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
EuiSpacer,
EuiText,
EuiLink,
EuiTitle,
} from '@elastic/eui';
import React from 'react';
import { OPENSEARCH_ACC_DOCUMENTATION_URL } from '../../../../common/constants';
Expand All @@ -20,7 +20,7 @@ export const CreateAccelerationHeader = () => {
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l" data-test-subj="acceleration-header">
<h1>Create Acceleration Index</h1>
<h1>Accelerate data</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
Expand Down
15 changes: 15 additions & 0 deletions public/components/acceleration/create/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { ACCELERATION_INDEX_NAME_REGEX } from '../../../../common/constants';

export const pluralizeTime = (timeWindow: number) => {
return timeWindow > 1 ? 's' : '';
Comment thread
ps48 marked this conversation as resolved.
};

export const validateIndexName = (value: string) => {
Comment thread
ps48 marked this conversation as resolved.
// Check if the value does not begin with underscores or hyphens and all characters are lower case
return ACCELERATION_INDEX_NAME_REGEX.test(value);
};
119 changes: 119 additions & 0 deletions public/components/acceleration/selectors/define_index_options.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
EuiButton,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiIconTip,
EuiLink,
EuiMarkdownFormat,
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import React, { ChangeEvent, useState } from 'react';
import { ACCELERATION_INDEX_NAME_INFO } from '../../../../common/constants';
import { CreateAccelerationForm } from '../../../../common/types';
import { validateIndexName } from '../create/utils';

interface DefineIndexOptionsProps {
accelerationFormData: CreateAccelerationForm;
setAccelerationFormData: React.Dispatch<React.SetStateAction<CreateAccelerationForm>>;
}

export const DefineIndexOptions = ({
accelerationFormData,
setAccelerationFormData,
}: DefineIndexOptionsProps) => {
const [indexName, setIndexName] = useState('');
const [modalComponent, setModalComponent] = useState(<></>);

const modalValue = (
<EuiModal maxWidth={850} onClose={() => setModalComponent(<></>)}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<h1>Acceleration index naming</h1>
</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiMarkdownFormat>{ACCELERATION_INDEX_NAME_INFO}</EuiMarkdownFormat>
</EuiFlexItem>
</EuiFlexGroup>
</EuiModalBody>
<EuiModalFooter>
<EuiButton onClick={() => setModalComponent(<></>)} fill>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>
);

const onChangeIndexName = (e: ChangeEvent<HTMLInputElement>) => {
setAccelerationFormData({ ...accelerationFormData, accelerationIndexName: e.target.value });
setIndexName(e.target.value);
};

const getPreprend = () => {
const dataSource =
accelerationFormData.dataSource !== ''
? accelerationFormData.dataSource
: '{Datasource Name}';
const database =
accelerationFormData.database !== '' ? accelerationFormData.database : '{Database Name}';
const dataTable =
accelerationFormData.dataTable !== '' ? accelerationFormData.dataTable : '{Table Name}';
const prependValue = `flint_${dataSource}_${database}_${dataTable}_`;
return [
prependValue,
<EuiIconTip type="iInCircle" color="subdued" content={prependValue} position="top" />,
];
};

const getAppend = () => {
const appendValue =
accelerationFormData.accelerationIndexType === 'materialized' ? '' : '_index';
return appendValue;
};

return (
<>
<EuiText data-test-subj="define-index-header">
<h3>Index settings</h3>
</EuiText>
<EuiSpacer size="s" />
<EuiFormRow
label="Index name"
helpText='Must be in lowercase letters. Cannot begin with underscores or hyphens. Spaces, commas, and characters :, ", *, +, /, \, |, ?, #, >, or < are not allowed.
Prefix and suffix are added to the name of generated OpenSearch index.'
labelAppend={
<EuiText size="xs">
<EuiLink onClick={() => setModalComponent(modalValue)}>Help</EuiLink>
</EuiText>
}
>
<EuiFieldText
placeholder="Enter index name"
value={accelerationFormData.accelerationIndexType === 'skipping' ? 'skipping' : indexName}
onChange={onChangeIndexName}
aria-label="Enter Index Name"
prepend={getPreprend()}
append={getAppend()}
disabled={accelerationFormData.accelerationIndexType === 'skipping'}
isInvalid={validateIndexName(indexName)}
/>
</EuiFormRow>
{modalComponent}
</>
);
};
Loading