Skip to content

Commit

Permalink
add some comments
Browse files Browse the repository at this point in the history
Signed-off-by: Kawika Avilla <kavilla414@gmail.com>

move language to left, some styling and disable per app name

Signed-off-by: Kawika Avilla <kavilla414@gmail.com>
  • Loading branch information
kavilla committed May 2, 2024
1 parent 0d0187b commit b6e6f8b
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 35 deletions.
15 changes: 14 additions & 1 deletion src/plugins/data/common/data_frames/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export interface DataFrameService {
clear: () => void;
}

/**
* A data frame is a two-dimensional labeled data structure with columns of potentially different types.
*/
export interface IDataFrame {
type?: DATA_FRAME_TYPES.DEFAULT;
name?: string;
Expand All @@ -29,13 +32,23 @@ export interface IDataFrame {
size: number;
}

/**
* An aggregation is a process where the values of multiple rows are grouped together to form a single summary value.
*/
export interface DataFrameAgg {
value: number;
}

/**
* A bucket aggregation is a type of aggregation that creates buckets or sets of data.
*/
export interface DataFrameBucketAgg extends DataFrameAgg {
key: string;
}

/**
* This configuration is used to define how the aggregation should be performed.
*/
export interface DataFrameAggConfig {
id: string;
type: string;
Expand Down Expand Up @@ -69,7 +82,7 @@ export interface PartialDataFrame extends Omit<IDataFrame, 'fields' | 'size'> {

/**
* To be utilize with aggregations and will map to buckets
* Plugins can get the aggreted value by their own logic
* Plugins can get the aggregated value by their own logic
* Setting to null will disable the aggregation if plugin wishes
* In future, if the plugin doesn't intentionally set the value to null,
* we can calculate the value based on the fields.
Expand Down
102 changes: 100 additions & 2 deletions src/plugins/data/common/data_frames/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,23 @@ import { IndexPatternFieldMap, IndexPatternSpec } from '../index_patterns';
import { IOpenSearchDashboardsSearchRequest } from '../search';
import { GetAggTypeFn, GetDataFrameAggQsFn } from '../types';

/**
* Returns the raw data frame from the search request.
*
* @param searchRequest - search request object.
* @returns dataframe
*/
export const getRawDataFrame = (searchRequest: IOpenSearchDashboardsSearchRequest) => {
return searchRequest.params?.body?.df;
};

/**
* Returns the raw query string from the search request.
* Gets current state query if exists, otherwise gets the initial query.
*
* @param searchRequest - search request object
* @returns query string
*/
export const getRawQueryString = (
searchRequest: IOpenSearchDashboardsSearchRequest
): string | undefined => {
Expand All @@ -32,10 +45,24 @@ export const getRawQueryString = (
);
};

/**
* Returns the raw aggregations from the search request.
*
* @param searchRequest - search request object
* @returns aggregations
*/
export const getRawAggs = (searchRequest: IOpenSearchDashboardsSearchRequest) => {
return searchRequest.params?.body?.aggs;
};

/**
* Returns the unique values for raw aggregations. This is used
* with `other-filter` aggregation. To get the values that were not
* included in the aggregation response prior to this request.
*
* @param rawAggs - raw aggregations object
* @returns object containing the field and its unique values
*/
export const getUniqueValuesForRawAggs = (rawAggs: Record<string, any>) => {
const filters = rawAggs.filters?.filters?.['']?.bool?.must_not;
if (!filters || !Array.isArray(filters)) {
Expand All @@ -56,6 +83,14 @@ export const getUniqueValuesForRawAggs = (rawAggs: Record<string, any>) => {
return { field, values };
};

/**
* Returns the aggregation configuration for raw aggregations.
* Aggregations are nested objects, so this function recursively
* builds an object that is easier to work with.
*
* @param rawAggs - raw aggregations object
* @returns aggregation configuration
*/
export const getAggConfigForRawAggs = (rawAggs: Record<string, any>): DataFrameAggConfig | null => {
const aggConfig: DataFrameAggConfig = { id: '', type: '' };

Expand All @@ -80,6 +115,14 @@ export const getAggConfigForRawAggs = (rawAggs: Record<string, any>): DataFrameA
return aggConfig;
};

/**
* Returns the aggregation configuration.
*
* @param searchRequest - search request object
* @param aggConfig - aggregation configuration object
* @param getAggTypeFn - function to get the aggregation type from the aggsService
* @returns aggregation configuration
*/
export const getAggConfig = (
searchRequest: IOpenSearchDashboardsSearchRequest,
aggConfig: Partial<DataFrameAggConfig> = {},
Expand Down Expand Up @@ -107,6 +150,14 @@ export const getAggConfig = (
return aggConfig as DataFrameAggConfig;
};

/**
* Converts the data frame response to a search response.
* This function is used to convert the data frame response to a search response
* to be used by the rest of the application.
*
* @param response - data frame response object
* @returns converted search response
*/
export const convertResult = (response: IDataFrameResponse): SearchResponse<any> => {
const body = response.body;
if (body.hasOwnProperty('error')) {
Expand Down Expand Up @@ -143,7 +194,7 @@ export const convertResult = (response: IDataFrameResponse): SearchResponse<any>
if (data.hasOwnProperty('aggs')) {
const dataWithAggs = data as IDataFrameWithAggs;
if (!dataWithAggs.aggs) {
// TODO: SQL best guess, get timestamp field and caculate it here
// TODO: MQL best guess, get timestamp field and caculate it here
return searchResponse;
}
searchResponse.aggregations = Object.entries(dataWithAggs.aggs).reduce(
Expand Down Expand Up @@ -187,10 +238,25 @@ export const convertResult = (response: IDataFrameResponse): SearchResponse<any>
return searchResponse;
};

/**
* Formats the field value.
*
* @param field - field object
* @param value - value to format
* @returns formatted value
*/
export const formatFieldValue = (field: IFieldType | Partial<IFieldType>, value: any): any => {
return field.format && field.format.convert ? field.format.convert(value) : value;
};

/**
* Returns the field type. This function is used to determine the field type so that can
* be used by the rest of the application. The field type must map to a OsdFieldType
* to be used by the rest of the application.
*
* @param field - field object
* @returns field type
*/
export const getFieldType = (field: IFieldType | Partial<IFieldType>): string | undefined => {
const fieldName = field.name?.toLowerCase();
if (fieldName?.includes('date') || fieldName?.includes('timestamp')) {
Expand All @@ -206,6 +272,14 @@ export const getFieldType = (field: IFieldType | Partial<IFieldType>): string |
return field.type;
};

/**
* Returns the time field. If there is an aggConfig then we do not have to guess.
* If there is no aggConfig then we will try to guess the time field.
*
* @param data - data frame object.
* @param aggConfig - aggregation configuration object.
* @returns time field.
*/
export const getTimeField = (
data: IDataFrame,
aggConfig?: DataFrameAggConfig
Expand All @@ -216,6 +290,12 @@ export const getTimeField = (
: fields.find((field) => field.type === 'date');
};

/**
* Checks if the value is a GeoPoint. Expects an object with lat and lon properties.
*
* @param value - value to check
* @returns True if the value is a GeoPoint, false otherwise
*/
export const isGeoPoint = (value: any): boolean => {
return (
typeof value === 'object' &&
Expand All @@ -227,6 +307,12 @@ export const isGeoPoint = (value: any): boolean => {
);
};

/**
* Creates a data frame.
*
* @param partial - partial data frame object
* @returns data frame.
*/
export const createDataFrame = (partial: PartialDataFrame): IDataFrame | IDataFrameWithAggs => {
let size = 0;
const processField = (field: any) => {
Expand All @@ -250,6 +336,12 @@ export const createDataFrame = (partial: PartialDataFrame): IDataFrame | IDataFr
};
};

/**
* Updates the data frame metadata. Metadata is used to store the aggregation configuration.
* It also stores the query string used to fetch the data frame aggregations.
*
* @param params - { dataFrame, qs, aggConfig, timeField, timeFilter, getAggQsFn }
*/
export const updateDataFrameMeta = ({
dataFrame,
qs,
Expand Down Expand Up @@ -291,6 +383,13 @@ export const updateDataFrameMeta = ({
}
};

/**
* Converts a data frame to index pattern spec which can be used to create an index pattern.
*
* @param dataFrame - data frame object
* @param id - index pattern id if it exists
* @returns index pattern spec
*/
export const dataFrameToSpec = (dataFrame: IDataFrame, id?: string): IndexPatternSpec => {
const fields = (dataFrame.schema || dataFrame.fields) as IFieldType[];

Expand Down Expand Up @@ -350,6 +449,5 @@ export const dataFrameToSpec = (dataFrame: IDataFrame, id?: string): IndexPatter
timeFieldName: getTimeField(dataFrame)?.name,
type: !id ? DATA_FRAME_TYPES.DEFAULT : undefined,
fields: fields.reduce(flattenFields, {} as IndexPatternFieldMap),
// TODO: SQL dataSourceRef
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ export class SearchSource {
await this.setDataFrame(dataFrameResponse.body as IDataFrame);
return onResponse(searchRequest, convertResult(response as IDataFrameResponse));
}
// TODO: SQL else if data_frame_polling then poll for the data frame updating the df fields only
// TODO: MQL else if data_frame_polling then poll for the data frame updating the df fields only
}
return onResponse(searchRequest, response.rawResponse);
});
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export class DataPublicPlugin
const uiService = this.uiService.setup(core, {});

return {
// TODO: SQL
// TODO: MQL
autocomplete: this.autocomplete.setup(core),
search: searchService,
fieldFormats: this.fieldFormatsService.setup(core),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// From: https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5623
.languageSwitcher {
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
.languageSelect {
max-width: 150px;
transform: translateY(-1px) translateX(-0.5px);
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface Props {
language: string;
onSelectLanguage: (newLanguage: string) => void;
anchorPosition?: PopoverAnchorPosition;
appName?: string;
}

function mapExternalLanguageToOptions(language: string) {
Expand Down Expand Up @@ -70,15 +71,22 @@ export function QueryLanguageSwitcher(props: Props) {

const queryEnhancements = uiService.queryEnhancements;
if (uiService.isEnhancementsEnabled) {
queryEnhancements.forEach((enhancement) =>
languageOptions.push(mapExternalLanguageToOptions(enhancement.language))
);
queryEnhancements.forEach((enhancement) => {
if (
enhancement.supportedAppNames &&
props.appName &&
!enhancement.supportedAppNames.includes(props.appName)
)
return;
languageOptions.push(mapExternalLanguageToOptions(enhancement.language));
});
}

const selectedLanguage = {
label: languageOptions.find(
(option) => (option.value as string).toLowerCase() === props.language.toLowerCase()
)?.label as string,
label:
(languageOptions.find(
(option) => (option.value as string).toLowerCase() === props.language.toLowerCase()
)?.label as string) ?? languageOptions[0].label,
};

const setSearchEnhance = (queryLanguage: string) => {
Expand Down Expand Up @@ -106,7 +114,7 @@ export function QueryLanguageSwitcher(props: Props) {

return (
<EuiComboBox
className="languageSwitcher"
className="languageSelect"
data-test-subj="languageSelect"
options={languageOptions}
selectedOptions={[selectedLanguage]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ export default function QueryBarTopRow(props: QueryBarTopRowProps) {
}

function shouldRenderQueryInput(): boolean {
// TODO: SQL probably can modify to not care about index patterns
// TODO: MQL probably can modify to not care about index patterns
// TODO: call queryUiEnhancement?.showQueryInput
return Boolean(props.showQueryInput && props.indexPatterns && props.query && storage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const KEY_CODES = {
};

// Needed for React.lazy
// TODO: SQL export this and let people extended this
// TODO: MQL export this and let people extended this
// eslint-disable-next-line import/no-default-export
export default class QueryStringInputUI extends Component<Props, State> {
public state: State = {
Expand Down Expand Up @@ -143,7 +143,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
return toUser(this.props.query.query);
};

// TODO: SQL don't do this here? || Fetch data sources
// TODO: MQL don't do this here? || Fetch data sources
private fetchIndexPatterns = async () => {
const stringPatterns = this.props.indexPatterns.filter(
(indexPattern) => typeof indexPattern === 'string'
Expand Down Expand Up @@ -468,7 +468,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
}
};

// TODO: SQL consider moving language select language of setting search source here
// TODO: MQL consider moving language select language of setting search source here
private onSelectLanguage = (language: string) => {
// Send telemetry info every time the user opts in or out of kuery
// As a result it is important this function only ever gets called in the
Expand Down Expand Up @@ -648,6 +648,14 @@ export default class QueryStringInputUI extends Component<Props, State> {
return (
<div className={className}>
{this.props.prepend}
{!!this.props.isEnhancementsEnabled && (
<QueryLanguageSwitcher
language={this.props.query.language}
anchorPosition={this.props.languageSwitcherPopoverAnchorPosition}
onSelectLanguage={this.onSelectLanguage}
appName={this.services.appName}
/>
)}
<EuiOutsideClickDetector onOutsideClick={this.onOutsideClick}>
<div
{...ariaCombobox}
Expand Down Expand Up @@ -725,13 +733,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
</EuiPortal>
</div>
</EuiOutsideClickDetector>
{!!this.props.isEnhancementsEnabled ? (
<QueryLanguageSwitcher
language={this.props.query.language}
anchorPosition={this.props.languageSwitcherPopoverAnchorPosition}
onSelectLanguage={this.onSelectLanguage}
/>
) : (
{!!!this.props.isEnhancementsEnabled && (
<LegacyQueryLanguageSwitcher
language={this.props.query.language}
anchorPosition={this.props.languageSwitcherPopoverAnchorPosition}
Expand Down
Loading

0 comments on commit b6e6f8b

Please sign in to comment.