Skip to content

Commit 89b6056

Browse files
authored
feat: allow date_nanos dates in timestamp selection (opensearch-project#795)
Signed-off-by: Babacar Diasse <babacar.diasse@corp.ovh.com>
1 parent 3d1245f commit 89b6056

File tree

4 files changed

+271
-2
lines changed

4 files changed

+271
-2
lines changed

public/pages/DefineDetector/components/Timestamp/Timestamp.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,15 @@ export function Timestamp(props: TimestampProps) {
5252
get(opensearchState, 'dataTypes.date', []) as string[]
5353
);
5454

55-
const timeStampFieldOptions = isEmpty(dateFields)
55+
const dateNanoFields = Array.from(
56+
get(opensearchState, 'dataTypes.date_nanos', []) as string[]
57+
);
58+
59+
const allDateFields = dateFields.concat(dateNanoFields);
60+
61+
const timeStampFieldOptions = isEmpty(allDateFields)
5662
? []
57-
: dateFields.map((dateField) => ({ label: dateField }));
63+
: allDateFields.map((dateField) => ({ label: dateField }));
5864

5965
return (
6066
<ContentPanel
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*
8+
* Modifications Copyright OpenSearch Contributors. See
9+
* GitHub history for details.
10+
*/
11+
12+
import React from 'react';
13+
import { Provider } from 'react-redux';
14+
import {
15+
HashRouter as Router,
16+
RouteComponentProps,
17+
Route,
18+
Switch,
19+
} from 'react-router-dom';
20+
import { render } from '@testing-library/react';
21+
import { Timestamp } from '../Timestamp';
22+
import { DetectorDefinitionFormikValues } from '../../../models/interfaces';
23+
import { CoreServicesContext } from '../../../../../components/CoreServices/CoreServices';
24+
import { FormikProps, Formik } from 'formik';
25+
import { coreServicesMock } from '../../../../../../test/mocks';
26+
27+
import { mockedStore } from '../../../../../redux/utils/testUtils';
28+
29+
const initialState = {
30+
opensearch: {
31+
indices: [
32+
{
33+
label: 'test-index',
34+
health: 'green',
35+
},
36+
],
37+
aliases: [],
38+
dataTypes: {
39+
date: ['created_at'],
40+
date_nanos: ['timestamp'],
41+
},
42+
requesting: false,
43+
searchResult: {},
44+
errorMessage: '',
45+
},
46+
};
47+
48+
const values = {
49+
name: 'test-ad',
50+
description: 'desc',
51+
index: [
52+
{
53+
label: 'test-index',
54+
health: 'green',
55+
},
56+
],
57+
filters: [],
58+
filterQuery: JSON.stringify({ bool: { filter: [] } }, null, 4),
59+
timeField: '',
60+
interval: 10,
61+
windowDelay: 1,
62+
} as DetectorDefinitionFormikValues;
63+
64+
const formikProps = {
65+
values: { values },
66+
errors: {},
67+
touched: {
68+
index: true,
69+
name: true,
70+
timeField: true,
71+
},
72+
isSubmitting: false,
73+
isValidating: false,
74+
submitCount: 0,
75+
initialErrors: {},
76+
initialTouched: {},
77+
isValid: true,
78+
dirty: true,
79+
validateOnBlur: true,
80+
validateOnChange: true,
81+
validateOnMount: true,
82+
} as FormikProps<DetectorDefinitionFormikValues>;
83+
84+
describe('<Timestamp /> spec', () => {
85+
test('renders the component', () => {
86+
const { container } = render(
87+
<Provider store={mockedStore(initialState)}>
88+
<Router>
89+
<Switch>
90+
<Route
91+
render={(props: RouteComponentProps) => (
92+
<CoreServicesContext.Provider value={coreServicesMock}>
93+
<Formik initialValues={values} onSubmit={jest.fn()}>
94+
<Timestamp formikProps={formikProps} />
95+
</Formik>
96+
</CoreServicesContext.Provider>
97+
)}
98+
/>
99+
</Switch>
100+
</Router>
101+
</Provider>
102+
);
103+
expect(container.firstChild).toMatchSnapshot();
104+
});
105+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<Timestamp /> spec renders the component 1`] = `
4+
<div
5+
class="euiPanel euiPanel--paddingMedium euiPanel--borderRadiusMedium euiPanel--plain euiPanel--hasShadow"
6+
style="padding: 20px;"
7+
>
8+
<div
9+
class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--alignItemsCenter euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive"
10+
style="padding: 0px;"
11+
>
12+
<div
13+
class="euiFlexItem"
14+
>
15+
<h3
16+
class="euiTitle euiTitle--small"
17+
data-test-subj="contentPanelTitle"
18+
>
19+
Timestamp
20+
</h3>
21+
<div
22+
class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive"
23+
>
24+
<div
25+
class="euiFlexItem content-panel-subTitle"
26+
style="line-height: normal; max-width: 75%;"
27+
>
28+
Select the time field you want to use for the time filter.
29+
</div>
30+
</div>
31+
</div>
32+
<div
33+
class="euiFlexItem euiFlexItem--flexGrowZero"
34+
>
35+
<div
36+
class="euiFlexGroup euiFlexGroup--gutterMedium euiFlexGroup--alignItemsCenter euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive"
37+
>
38+
<div
39+
class="euiFlexItem"
40+
/>
41+
</div>
42+
</div>
43+
</div>
44+
<div>
45+
<hr
46+
class="euiHorizontalRule euiHorizontalRule--full euiHorizontalRule--marginSmall"
47+
/>
48+
<div
49+
style="padding: 10px 0px;"
50+
>
51+
<div
52+
class="euiFormRow"
53+
hint="Choose the time field you want to use for time filter."
54+
id="random_html_id-row"
55+
title="Timestamp field"
56+
>
57+
<div
58+
class="euiFormRow__labelWrapper"
59+
>
60+
<label
61+
aria-invalid="false"
62+
class="euiFormLabel euiFormRow__label"
63+
for="random_html_id"
64+
>
65+
<div
66+
style="line-height: 8px;"
67+
>
68+
<p>
69+
Timestamp field
70+
</p>
71+
<br />
72+
<div
73+
class="euiText euiText--medium sublabel"
74+
style="max-width: 400px;"
75+
>
76+
Choose the time field you want to use for time filter.
77+
</div>
78+
</div>
79+
</label>
80+
</div>
81+
<div
82+
class="euiFormRow__fieldWrapper"
83+
>
84+
<div
85+
aria-expanded="false"
86+
aria-haspopup="listbox"
87+
class="euiComboBox"
88+
data-test-subj="timestampFilter"
89+
role="combobox"
90+
>
91+
<div
92+
class="euiFormControlLayout"
93+
>
94+
<div
95+
class="euiFormControlLayout__childrenWrapper"
96+
>
97+
<div
98+
class="euiComboBox__inputWrap euiComboBox__inputWrap--noWrap"
99+
data-test-subj="comboBoxInput"
100+
tabindex="-1"
101+
>
102+
<p
103+
class="euiComboBoxPlaceholder"
104+
>
105+
Find timestamp
106+
</p>
107+
<div
108+
class="euiComboBox__input"
109+
style="font-size: 14px; display: inline-block;"
110+
>
111+
<input
112+
aria-controls=""
113+
data-test-subj="comboBoxSearchInput"
114+
id="random_html_id"
115+
role="textbox"
116+
style="box-sizing: content-box; width: 2px;"
117+
value=""
118+
/>
119+
<div
120+
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
121+
/>
122+
</div>
123+
</div>
124+
<div
125+
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
126+
>
127+
<button
128+
aria-label="Open list of options"
129+
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
130+
data-test-subj="comboBoxToggleListButton"
131+
type="button"
132+
>
133+
<svg
134+
aria-hidden="true"
135+
class="euiIcon euiIcon--medium euiIcon-isLoading euiFormControlLayoutCustomIcon__icon"
136+
focusable="false"
137+
height="16"
138+
role="img"
139+
viewBox="0 0 16 16"
140+
width="16"
141+
xmlns="http://www.w3.org/2000/svg"
142+
>
143+
<path
144+
d="M5.277 10.088c.02.014.04.03.057.047.582.55 1.134.812 1.666.812.586 0 1.84-.293 3.713-.88L9 6.212V2H7v4.212l-1.723 3.876Zm-.438.987L3.539 14h8.922l-1.32-2.969C9.096 11.677 7.733 12 7 12c-.74 0-1.463-.315-2.161-.925ZM6 2H5V1h6v1h-1v4l3.375 7.594A1 1 0 0 1 12.461 15H3.54a1 1 0 0 1-.914-1.406L6 6V2Z"
145+
/>
146+
</svg>
147+
</button>
148+
</div>
149+
</div>
150+
</div>
151+
</div>
152+
</div>
153+
</div>
154+
</div>
155+
</div>
156+
</div>
157+
`;

public/redux/reducers/opensearch.ts

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export interface DataTypes {
4545
half_float?: string[];
4646
boolean?: string[];
4747
date?: string[];
48+
date_nanos?: string[];
4849
keyword?: string[];
4950
text?: string[];
5051
integer_range?: string[];

0 commit comments

Comments
 (0)