From 5d97d3c1f7575baebda00363737c79080a545e4b Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Sat, 23 Nov 2024 05:15:32 +0000 Subject: [PATCH 1/4] Pass time filter if language overrides hideDatePicker Signed-off-by: Joshua Li --- .../query_string/dataset_service/types.ts | 9 ++- .../query_string/language_service/types.ts | 5 ++ .../ui/dataset_selector/configurator.tsx | 40 ++++++++---- .../ui/query_editor/query_editor_top_row.tsx | 65 ++++++++++++++++--- .../query_enhancements/common/types.ts | 7 +- .../query_enhancements/common/utils.ts | 1 + .../public/search/ppl_search_interceptor.ts | 21 +++++- .../public/search/sql_search_interceptor.ts | 11 ++++ .../query_enhancements/server/routes/index.ts | 1 + 9 files changed, 133 insertions(+), 27 deletions(-) diff --git a/src/plugins/data/public/query/query_string/dataset_service/types.ts b/src/plugins/data/public/query/query_string/dataset_service/types.ts index 65c322acec6f..4b1cbb553ad7 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/types.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/types.ts @@ -43,6 +43,13 @@ export interface DatasetTypeConfig { id: string; /** Human-readable title for the dataset type */ title: string; + languageOverrides?: { + [language: string]: { + /** The overrides transfer the responsibility of handling the input from + * the language interceptor to the dataset types strategy. */ + hideDatePicker?: boolean; + }; + }; /** Metadata for UI representation */ meta: { /** Icon to represent the dataset type */ @@ -51,7 +58,7 @@ export interface DatasetTypeConfig { tooltip?: string; /** Optional preference for search on page load else defaulted to true */ searchOnLoad?: boolean; - /** Optional supportsTimeFilter determines if a time filter is needed */ + /** Optional supportsTimeFilter determines if a time field is supported */ supportsTimeFilter?: boolean; /** Optional isFieldLoadAsync determines if field loads are async */ isFieldLoadAsync?: boolean; diff --git a/src/plugins/data/public/query/query_string/language_service/types.ts b/src/plugins/data/public/query/query_string/language_service/types.ts index c80858d67102..6404aa98ed65 100644 --- a/src/plugins/data/public/query/query_string/language_service/types.ts +++ b/src/plugins/data/public/query/query_string/language_service/types.ts @@ -61,6 +61,11 @@ export interface LanguageConfig { }; editorSupportedAppNames?: string[]; supportedAppNames?: string[]; + /** + * @deprecated + * + * Use `datasetTypeConfig.supportsTimeFilter` instead + */ hideDatePicker?: boolean; sampleQueries?: SampleQuery[]; } diff --git a/src/plugins/data/public/ui/dataset_selector/configurator.tsx b/src/plugins/data/public/ui/dataset_selector/configurator.tsx index 0dba9107934c..4906bec2ef84 100644 --- a/src/plugins/data/public/ui/dataset_selector/configurator.tsx +++ b/src/plugins/data/public/ui/dataset_selector/configurator.tsx @@ -69,6 +69,7 @@ export const Configurator = ({ const [selectedIndexedView, setSelectedIndexedView] = useState(); const [indexedViews, setIndexedViews] = useState([]); const [isLoadingIndexedViews, setIsLoadingIndexedViews] = useState(false); + const [timeFieldsLoading, setTimeFieldsLoading] = useState(false); useEffect(() => { let isMounted = true; @@ -91,23 +92,26 @@ export const Configurator = ({ const submitDisabled = useMemo(() => { return ( - timeFieldName === undefined && - !( - languageService.getLanguage(language)?.hideDatePicker || - dataset.type === DEFAULT_DATA.SET_TYPES.INDEX_PATTERN - ) && - timeFields && - timeFields.length > 0 + timeFieldsLoading || + (timeFieldName === undefined && + !(dataset.type === DEFAULT_DATA.SET_TYPES.INDEX_PATTERN) && + timeFields && + timeFields.length > 0) ); - }, [dataset, language, timeFieldName, timeFields, languageService]); + }, [dataset, timeFieldName, timeFields, timeFieldsLoading]); useEffect(() => { const fetchFields = async () => { - const datasetFields = await queryString - .getDatasetService() - .getType(baseDataset.type) - ?.fetchFields(baseDataset); + const datasetType = queryString.getDatasetService().getType(baseDataset.type); + if (!datasetType) { + setTimeFields([]); + return; + } + setTimeFieldsLoading(true); + const datasetFields = await datasetType + .fetchFields(baseDataset) + .finally(() => setTimeFieldsLoading(false)); const dateFields = datasetFields?.filter((field) => field.type === 'date'); setTimeFields(dateFields || []); }; @@ -152,6 +156,16 @@ export const Configurator = ({ }; }, [indexedViewsService, selectedIndexedView, dataset]); + const shouldRenderDatePickerField = useCallback(() => { + const datasetType = queryString.getDatasetService().getType(dataset.type); + + const supportsTimeField = datasetType?.meta?.supportsTimeFilter; + if (supportsTimeField !== undefined) { + return Boolean(supportsTimeField); + } + return true; + }, [dataset.type, queryString]); + return ( <> @@ -256,7 +270,7 @@ export const Configurator = ({ data-test-subj="advancedSelectorLanguageSelect" /> - {!languageService.getLanguage(language)?.hideDatePicker && + {shouldRenderDatePickerField() && (dataset.type === DEFAULT_DATA.SET_TYPES.INDEX_PATTERN ? ( true + * - showDatePicker=false && showAutoRefreshOnly=false => false + * - both undefined => true (default) + * If isDatePickerEnabled is false, returns false immediately + * + * Dataset Type permutations (datasetType?.meta?.supportsTimeFilter): + * - supportsTimeFilter=true => true + * - supportsTimeFilter=false => false + * - supportsTimeFilter=undefined && dataset exists => falls through to language check + * - no dataset => falls through to language check + * + * Language permutations (when dataset.meta.supportsTimeFilter is undefined): + * - queryLanguage=undefined => true (shows date picker) + * - queryLanguage exists: + * - hideDatePicker=true => false + * - hideDatePicker=false => true + * - hideDatePicker=undefined => true + * + * Example scenarios: + * 1. {showDatePicker: false} => false + * 2. {dataset: {type: 'x', meta: {supportsTimeFilter: true}}} => true + * 3. {dataset: {type: 'x', meta: {supportsTimeFilter: false}}} => false + * 4. {dataset: {type: 'x'}, queryLanguage: 'sql', hideDatePicker: true} => false + * 5. {dataset: {type: 'x'}, queryLanguage: 'sql', hideDatePicker: false} => true + * 6. {dataset: {type: 'x'}, queryLanguage: undefined} => true (no language restrictions) + * 7. No configuration => true (default behavior shows date picker) + */ function shouldRenderDatePicker(): boolean { - return ( - Boolean((props.showDatePicker || props.showAutoRefreshOnly) ?? true) && - !( - queryLanguage && - data.query.queryString.getLanguageService().getLanguage(queryLanguage)?.hideDatePicker - ) && - (props.query?.dataset - ? data.query.queryString.getDatasetService().getType(props.query.dataset.type)?.meta - ?.supportsTimeFilter !== false - : true) + const { queryString } = data.query; + const datasetService = queryString.getDatasetService(); + const languageService = queryString.getLanguageService(); + const isDatePickerEnabled = Boolean( + (props.showDatePicker || props.showAutoRefreshOnly) ?? true ); + if (!isDatePickerEnabled) return false; + + // Get dataset type configuration + const datasetType = props.query?.dataset + ? datasetService.getType(props.query?.dataset.type) + : undefined; + // Check if dataset type explicitly configures the `supportsTimeFilter` option + if (datasetType?.meta?.supportsTimeFilter === false) return false; + + if ( + queryLanguage && + datasetType?.languageOverrides?.[queryLanguage]?.hideDatePicker !== undefined + ) { + return Boolean(!datasetType.languageOverrides[queryLanguage].hideDatePicker); + } + + return Boolean(!(queryLanguage && languageService.getLanguage(queryLanguage)?.hideDatePicker)); } function shouldRenderQueryEditor(): boolean { diff --git a/src/plugins/query_enhancements/common/types.ts b/src/plugins/query_enhancements/common/types.ts index 1bb977527d4a..2f73ca52d496 100644 --- a/src/plugins/query_enhancements/common/types.ts +++ b/src/plugins/query_enhancements/common/types.ts @@ -4,7 +4,7 @@ */ import { CoreSetup } from 'opensearch-dashboards/public'; -import { PollQueryResultsParams } from '../../data/common'; +import { PollQueryResultsParams, TimeRange } from '../../data/common'; export interface QueryAggConfig { [key: string]: { @@ -26,7 +26,10 @@ export interface EnhancedFetchContext { http: CoreSetup['http']; path: string; signal?: AbortSignal; - body?: { pollQueryResultsParams: PollQueryResultsParams }; + body?: { + pollQueryResultsParams?: PollQueryResultsParams; + timeRange?: TimeRange; + }; } export interface QueryStatusOptions { diff --git a/src/plugins/query_enhancements/common/utils.ts b/src/plugins/query_enhancements/common/utils.ts index 9b2bb9e3aacf..cdb8fb05c08b 100644 --- a/src/plugins/query_enhancements/common/utils.ts +++ b/src/plugins/query_enhancements/common/utils.ts @@ -55,6 +55,7 @@ export const fetch = (context: EnhancedFetchContext, query: Query, aggConfig?: Q query: { ...query, format: 'jdbc' }, aggConfig, pollQueryResultsParams: context.body?.pollQueryResultsParams, + timeRange: context.body?.timeRange, }); return from( http.fetch({ diff --git a/src/plugins/query_enhancements/public/search/ppl_search_interceptor.ts b/src/plugins/query_enhancements/public/search/ppl_search_interceptor.ts index 57152dbe98ea..ecfe32ff8a75 100644 --- a/src/plugins/query_enhancements/public/search/ppl_search_interceptor.ts +++ b/src/plugins/query_enhancements/public/search/ppl_search_interceptor.ts @@ -50,6 +50,7 @@ export class PPLSearchInterceptor extends SearchInterceptor { signal, body: { pollQueryResultsParams: request.params?.pollQueryResultsParams, + timeRange: request.params?.body?.timeRange, }, }; @@ -68,15 +69,33 @@ export class PPLSearchInterceptor extends SearchInterceptor { .getDatasetService() .getType(datasetType); strategy = datasetTypeConfig?.getSearchOptions?.().strategy ?? strategy; + + if ( + dataset?.timeFieldName && + datasetTypeConfig?.languageOverrides?.PPL?.hideDatePicker === false + ) { + request.params = { + ...request.params, + body: { + ...request.params.body, + timeRange: this.queryService.timefilter.timefilter.getTime(), + }, + }; + } } return this.runSearch(request, options.abortSignal, strategy); } private buildQuery() { - const query: Query = this.queryService.queryString.getQuery(); + const { queryString } = this.queryService; + const query: Query = queryString.getQuery(); const dataset = query.dataset; if (!dataset || !dataset.timeFieldName) return query; + const datasetService = queryString.getDatasetService(); + if (datasetService.getType(dataset.type)?.languageOverrides?.PPL?.hideDatePicker === false) + return query; + const [baseQuery, ...afterPipeParts] = query.query.split('|'); const afterPipe = afterPipeParts.length > 0 ? ` | ${afterPipeParts.join('|').trim()}` : ''; const timeFilter = this.getTimeFilter(dataset.timeFieldName); diff --git a/src/plugins/query_enhancements/public/search/sql_search_interceptor.ts b/src/plugins/query_enhancements/public/search/sql_search_interceptor.ts index 9fe17fc79322..9f93dd067cb3 100644 --- a/src/plugins/query_enhancements/public/search/sql_search_interceptor.ts +++ b/src/plugins/query_enhancements/public/search/sql_search_interceptor.ts @@ -42,6 +42,7 @@ export class SQLSearchInterceptor extends SearchInterceptor { signal, body: { pollQueryResultsParams: request.params?.pollQueryResultsParams, + timeRange: request.params?.body?.timeRange, }, }; @@ -62,6 +63,16 @@ export class SQLSearchInterceptor extends SearchInterceptor { .getDatasetService() .getType(datasetType); strategy = datasetTypeConfig?.getSearchOptions?.().strategy ?? strategy; + + if (datasetTypeConfig?.languageOverrides?.SQL?.hideDatePicker === false) { + request.params = { + ...request.params, + body: { + ...request.params.body, + timeRange: this.queryService.timefilter.timefilter.getTime(), + }, + }; + } } return this.runSearch(request, options.abortSignal, strategy); diff --git a/src/plugins/query_enhancements/server/routes/index.ts b/src/plugins/query_enhancements/server/routes/index.ts index 79b93a279272..20928c5529f4 100644 --- a/src/plugins/query_enhancements/server/routes/index.ts +++ b/src/plugins/query_enhancements/server/routes/index.ts @@ -77,6 +77,7 @@ export function defineSearchStrategyRouteProvider(logger: Logger, router: IRoute sessionId: schema.maybe(schema.string()), }) ), + timeRange: schema.maybe(schema.object({}, { unknowns: 'allow' })), }), }, }, From 0ff21ebf5a12f079c594751100c658469661f1d2 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Tue, 26 Nov 2024 21:07:51 +0000 Subject: [PATCH 2/4] update outdated comments Signed-off-by: Joshua Li --- .../query/query_string/dataset_service/types.ts | 4 ++-- .../query/query_string/language_service/types.ts | 5 ----- .../ui/query_editor/query_editor_top_row.tsx | 16 +++------------- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/plugins/data/public/query/query_string/dataset_service/types.ts b/src/plugins/data/public/query/query_string/dataset_service/types.ts index 4b1cbb553ad7..d97afec8abb6 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/types.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/types.ts @@ -45,8 +45,8 @@ export interface DatasetTypeConfig { title: string; languageOverrides?: { [language: string]: { - /** The overrides transfer the responsibility of handling the input from - * the language interceptor to the dataset types strategy. */ + /** The override transfers the responsibility of handling the input from + * the language interceptor to the dataset type search strategy. */ hideDatePicker?: boolean; }; }; diff --git a/src/plugins/data/public/query/query_string/language_service/types.ts b/src/plugins/data/public/query/query_string/language_service/types.ts index 6404aa98ed65..c80858d67102 100644 --- a/src/plugins/data/public/query/query_string/language_service/types.ts +++ b/src/plugins/data/public/query/query_string/language_service/types.ts @@ -61,11 +61,6 @@ export interface LanguageConfig { }; editorSupportedAppNames?: string[]; supportedAppNames?: string[]; - /** - * @deprecated - * - * Use `datasetTypeConfig.supportsTimeFilter` instead - */ hideDatePicker?: boolean; sampleQueries?: SampleQuery[]; } diff --git a/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx b/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx index c13005de799b..ad22750207ed 100644 --- a/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx +++ b/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx @@ -236,26 +236,16 @@ export default function QueryEditorTopRow(props: QueryEditorTopRowProps) { * If isDatePickerEnabled is false, returns false immediately * * Dataset Type permutations (datasetType?.meta?.supportsTimeFilter): - * - supportsTimeFilter=true => true * - supportsTimeFilter=false => false - * - supportsTimeFilter=undefined && dataset exists => falls through to language check - * - no dataset => falls through to language check * - * Language permutations (when dataset.meta.supportsTimeFilter is undefined): + * Language permutations (when dataset.meta.supportsTimeFilter is undefined or true): * - queryLanguage=undefined => true (shows date picker) * - queryLanguage exists: + * - languageOverrides[queryLanguage].hideDatePicker=true => false + * - languageOverrides[queryLanguage].hideDatePicker=false => true * - hideDatePicker=true => false * - hideDatePicker=false => true * - hideDatePicker=undefined => true - * - * Example scenarios: - * 1. {showDatePicker: false} => false - * 2. {dataset: {type: 'x', meta: {supportsTimeFilter: true}}} => true - * 3. {dataset: {type: 'x', meta: {supportsTimeFilter: false}}} => false - * 4. {dataset: {type: 'x'}, queryLanguage: 'sql', hideDatePicker: true} => false - * 5. {dataset: {type: 'x'}, queryLanguage: 'sql', hideDatePicker: false} => true - * 6. {dataset: {type: 'x'}, queryLanguage: undefined} => true (no language restrictions) - * 7. No configuration => true (default behavior shows date picker) */ function shouldRenderDatePicker(): boolean { const { queryString } = data.query; From a0ea03214b71cb444042d84c650b437b73b073ed Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Tue, 26 Nov 2024 21:59:09 +0000 Subject: [PATCH 3/4] update tests Signed-off-by: Joshua Li --- .../dataset_service/dataset_service.mock.ts | 3 + .../ui/dataset_selector/configurator.test.tsx | 72 +++++++++++++++++-- .../query_editor_top_row.test.tsx | 62 ++++++++++++++-- 3 files changed, 126 insertions(+), 11 deletions(-) diff --git a/src/plugins/data/public/query/query_string/dataset_service/dataset_service.mock.ts b/src/plugins/data/public/query/query_string/dataset_service/dataset_service.mock.ts index df5521078feb..ba491cb51191 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/dataset_service.mock.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/dataset_service.mock.ts @@ -43,6 +43,9 @@ const createSetupDatasetServiceMock = (): jest.Mocked => fetchOptions: jest.fn(), getRecentDatasets: jest.fn(), addRecentDataset: jest.fn(), + clearCache: jest.fn(), + getLastCacheTime: jest.fn(), + removeFromRecentDatasets: jest.fn(), }; }; diff --git a/src/plugins/data/public/ui/dataset_selector/configurator.test.tsx b/src/plugins/data/public/ui/dataset_selector/configurator.test.tsx index 462c6298a0a3..38d4e4e12183 100644 --- a/src/plugins/data/public/ui/dataset_selector/configurator.test.tsx +++ b/src/plugins/data/public/ui/dataset_selector/configurator.test.tsx @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import { Configurator } from './configurator'; import '@testing-library/jest-dom'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { setQueryService, setIndexPatterns } from '../../services'; import { IntlProvider } from 'react-intl'; -import { Query } from '../../../../data/public'; import { Dataset } from 'src/plugins/data/common'; +import { Query } from '../../../../data/public'; +import { setIndexPatterns, setQueryService } from '../../services'; +import { Configurator } from './configurator'; const getQueryMock = jest.fn().mockReturnValue({ query: '', @@ -358,4 +358,68 @@ describe('Configurator Component', () => { expect(submitButton).toBeEnabled(); }); }); + + it('should show the date picker if supportsTimeFilter is undefined', async () => { + const mockDataset = { + ...mockBaseDataset, + timeFieldName: undefined, + type: 'index', + }; + const { container } = render( + + + + ); + + expect( + container.querySelector(`[data-test-subj="advancedSelectorTimeFieldSelect"]`) + ).toBeTruthy(); + }); + + it('should hide the date picker if supportsTimeFilter is false', async () => { + const mockDataset = { + ...mockBaseDataset, + timeFieldName: undefined, + type: 'index', + }; + const datasetTypeConfig = mockServices + .getQueryService() + .queryString.getDatasetService() + .getType(); + mockServices + .getQueryService() + .queryString.getDatasetService() + .getType.mockReturnValue({ + ...datasetTypeConfig, + meta: { + supportsTimeFilter: false, + }, + }); + const { container } = render( + + + + ); + + expect( + container.querySelector(`[data-test-subj="advancedSelectorTimeFieldSelect"]`) + ).toBeFalsy(); + + mockServices + .getQueryService() + .queryString.getDatasetService() + .getType.mockReturnValue(datasetTypeConfig); + }); }); diff --git a/src/plugins/data/public/ui/query_editor/query_editor_top_row.test.tsx b/src/plugins/data/public/ui/query_editor/query_editor_top_row.test.tsx index 62fe653bfd45..284cbe8d4ff0 100644 --- a/src/plugins/data/public/ui/query_editor/query_editor_top_row.test.tsx +++ b/src/plugins/data/public/ui/query_editor/query_editor_top_row.test.tsx @@ -3,15 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Query, UI_SETTINGS } from '../../../common'; -import { coreMock } from '../../../../../core/public/mocks'; -import { dataPluginMock } from '../../mocks'; -import React from 'react'; import { I18nProvider } from '@osd/i18n/react'; -import { createEditor, DQLBody, QueryEditorTopRow, SingleLineInput } from '../'; -import { OpenSearchDashboardsContextProvider } from 'src/plugins/opensearch_dashboards_react/public'; import { cleanup, render, waitFor } from '@testing-library/react'; -import { LanguageConfig } from '../../query'; +import React from 'react'; +import { OpenSearchDashboardsContextProvider } from 'src/plugins/opensearch_dashboards_react/public'; +import { createEditor, DQLBody, QueryEditorTopRow, SingleLineInput } from '../'; +import { coreMock } from '../../../../../core/public/mocks'; +import { Query, UI_SETTINGS } from '../../../common'; +import { dataPluginMock } from '../../mocks'; +import { DatasetTypeConfig, LanguageConfig } from '../../query'; +import { datasetServiceMock } from '../../query/query_string/dataset_service/dataset_service.mock'; import { getQueryService } from '../../services'; const startMock = coreMock.createStart(); @@ -66,6 +67,7 @@ const createMockStorage = () => ({ }); const dataPlugin = dataPluginMock.createStartContract(true); +const datasetService = datasetServiceMock.createStartContract(); function wrapQueryEditorTopRowInContext(testProps: any) { const defaultOptions = { @@ -111,6 +113,7 @@ describe('QueryEditorTopRow', () => { beforeEach(() => { jest.clearAllMocks(); (getQueryService as jest.Mock).mockReturnValue(dataPlugin.query); + dataPlugin.query.queryString.getDatasetService = jest.fn().mockReturnValue(datasetService); }); afterEach(() => { @@ -155,4 +158,49 @@ describe('QueryEditorTopRow', () => { await waitFor(() => expect(container.querySelector(QUERY_EDITOR)).toBeTruthy()); expect(container.querySelector(DATE_PICKER)).toBeFalsy(); }); + + it('Should not render date picker if dataset type does not support time field', async () => { + const query: Query = { + query: 'test query', + dataset: datasetService.getDefault(), + language: 'test-language', + }; + dataPlugin.query.queryString.getQuery = jest.fn().mockReturnValue(query); + datasetService.getType.mockReturnValue({ + meta: { supportsTimeFilter: false }, + } as DatasetTypeConfig); + + const { container } = render( + wrapQueryEditorTopRowInContext({ + query, + showQueryEditor: false, + showDatePicker: true, + }) + ); + await waitFor(() => expect(container.querySelector(QUERY_EDITOR)).toBeTruthy()); + expect(container.querySelector(DATE_PICKER)).toBeFalsy(); + }); + + it('Should render date picker if dataset overrides hideDatePicker to false', async () => { + const query: Query = { + query: 'test query', + dataset: datasetService.getDefault(), + language: 'test-language', + }; + dataPlugin.query.queryString.getQuery = jest.fn().mockReturnValue(query); + datasetService.getType.mockReturnValue(({ + meta: { supportsTimeFilter: true }, + languageOverrides: { 'test-language': { hideDatePicker: false } }, + } as unknown) as DatasetTypeConfig); + + const { container } = render( + wrapQueryEditorTopRowInContext({ + query, + showQueryEditor: false, + showDatePicker: true, + }) + ); + await waitFor(() => expect(container.querySelector(QUERY_EDITOR)).toBeTruthy()); + expect(container.querySelector(DATE_PICKER)).toBeTruthy(); + }); }); From 7f6b2fcec3c32ecf04803c34b13e1c56a1288907 Mon Sep 17 00:00:00 2001 From: "opensearch-changeset-bot[bot]" <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:00:52 +0000 Subject: [PATCH 4/4] Changeset file for PR #8932 created/updated --- changelogs/fragments/8932.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/8932.yml diff --git a/changelogs/fragments/8932.yml b/changelogs/fragments/8932.yml new file mode 100644 index 000000000000..a048de0a102a --- /dev/null +++ b/changelogs/fragments/8932.yml @@ -0,0 +1,2 @@ +feat: +- Support custom logic to insert time filter based on dataset type ([#8932](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8932)) \ No newline at end of file