Skip to content

Commit da59f80

Browse files
authored
feat: nifi timestamp precision (#4947)
1 parent 97bfee5 commit da59f80

File tree

11 files changed

+294
-113
lines changed

11 files changed

+294
-113
lines changed

cypress/e2e/cloud/subscriptions.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ describe('Subscriptions', () => {
227227
cy.getByTestID('heading')
228228
.should('be.visible')
229229
.contains('Data Format')
230+
cy.getByTestID('lp-timestamp-precision')
231+
.scrollIntoView()
232+
.should('be.visible')
233+
.contains('NS')
230234
cy.getByTestID('update-sub-form--submit')
231235
.should('be.visible')
232236
.click()
@@ -293,6 +297,13 @@ describe('Subscriptions', () => {
293297
// json
294298
cy.getByTestID('create-parsing-form-json--button').click()
295299
cy.getByTestID('timestamp-json-parsing').type('$.t')
300+
cy.getByTestID('json-timestamp-precision')
301+
.scrollIntoView()
302+
.should('be.visible')
303+
.click()
304+
cy.getByTestID('json-timestamp-precision-Nanoseconds')
305+
.first()
306+
.click()
296307
cy.getByTestID('measurement-json-parsing-type')
297308
.contains('String')
298309
.click()
@@ -373,6 +384,10 @@ describe('Subscriptions', () => {
373384
cy.getByTestID('heading')
374385
.should('be.visible')
375386
.contains('Data Format')
387+
cy.getByTestID('json-timestamp-precision')
388+
.scrollIntoView()
389+
.should('be.visible')
390+
.contains('NS')
376391
cy.getByTestID('measurement-json-parsing-path')
377392
.scrollIntoView()
378393
.should('be.visible')
@@ -475,6 +490,13 @@ describe('Subscriptions', () => {
475490
// string
476491
cy.getByTestID('create-parsing-form-string--button').click()
477492
cy.getByTestID('timestamp-string-parsing').type('0123456789')
493+
cy.getByTestID('string-timestamp-precision')
494+
.scrollIntoView()
495+
.should('be.visible')
496+
.click()
497+
cy.getByTestID('string-timestamp-precision-Nanoseconds')
498+
.first()
499+
.click()
478500
cy.getByTestID('measurment-string-parsing-pattern').type('m=//m')
479501
// add tag
480502
cy.getByTestID('string-parsing-add-rule').click()
@@ -543,6 +565,10 @@ describe('Subscriptions', () => {
543565
.should('be.visible')
544566
.clear()
545567
.type('m1=//m1')
568+
cy.getByTestID('string-timestamp-precision')
569+
.scrollIntoView()
570+
.should('be.visible')
571+
.contains('NS')
546572
cy.getByTestID('timestamp-string-parsing')
547573
.clear()
548574
.type('987654321')
@@ -635,6 +661,7 @@ describe('Subscriptions', () => {
635661
isActive: true,
636662
flowVersion: 5,
637663
status: 'ERRORED',
664+
timestampPrecision: 'NS',
638665
}
639666
const subscription = 'My Subscription'
640667
createBasicLPSubscription(subscription)

src/types/subscriptions.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface Subscription {
2828
token?: string
2929
isActive?: string
3030
flowVersion?: number
31+
timestampPrecision?: string
3132
}
3233

3334
export interface JsonSpec {
@@ -40,3 +41,10 @@ export interface StringObjectParams {
4041
pattern?: string
4142
name?: string
4243
}
44+
45+
export enum PrecisionTypes {
46+
Milliseconds = 'MS',
47+
Seconds = 'S',
48+
Microseconds = 'US',
49+
Nanoseconds = 'NS',
50+
}

src/writeData/subscriptions/components/JsonParsingForm.tsx

Lines changed: 90 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,18 @@ import {
2222
import JsonPathInput from 'src/writeData/subscriptions/components/JsonPathInput'
2323

2424
// Types
25-
import {Subscription} from 'src/types/subscriptions'
25+
import {Subscription, PrecisionTypes} from 'src/types/subscriptions'
2626

2727
// Utils
2828
import {
2929
sanitizeType,
3030
handleValidation,
3131
handleJsonPathValidation,
3232
} from 'src/writeData/subscriptions/utils/form'
33+
import {event} from 'src/cloud/utils/reporting'
3334

3435
// Styles
3536
import 'src/writeData/subscriptions/components/JsonParsingForm.scss'
36-
import {event} from 'src/cloud/utils/reporting'
3737

3838
interface Props {
3939
formContent: Subscription
@@ -72,44 +72,96 @@ const JsonParsingForm: FC<Props> = ({formContent, updateForm, edit}) => {
7272
return (
7373
<div className="json-parsing-form">
7474
<Grid.Column>
75-
<Form.ValidationElement
76-
label="JSON Path to Timestmap"
77-
value={formContent.jsonTimestamp?.path}
78-
required={false}
79-
validationFunc={() =>
80-
!!formContent.jsonTimestamp?.path
81-
? handleJsonPathValidation(formContent.jsonTimestamp?.path)
82-
: null
83-
}
75+
<FlexBox
76+
alignItems={AlignItems.FlexStart}
77+
direction={FlexDirection.Row}
78+
margin={ComponentSize.Large}
79+
className="json-parsing-form__container"
8480
>
85-
{status => (
86-
<Input
87-
type={InputType.Text}
88-
placeholder="eg. $.myJSON.myObject[0].timestampKey"
89-
name="timestamp"
90-
autoFocus={true}
91-
value={formContent.jsonTimestamp?.path}
92-
onChange={e => {
93-
updateForm({
94-
...formContent,
95-
jsonTimestamp: {
96-
...formContent.jsonTimestamp,
97-
path: e.target.value,
98-
},
99-
})
100-
}}
101-
onBlur={() =>
102-
event(
103-
'completed form field',
104-
{formField: 'jsonTimestamp.path'},
105-
{feature: 'subscriptions'}
106-
)
107-
}
108-
testID="timestamp-json-parsing"
109-
status={edit ? status : ComponentStatus.Disabled}
81+
<Form.ValidationElement
82+
label="JSON Path to Timestamp"
83+
value={formContent.jsonTimestamp?.path}
84+
required={false}
85+
validationFunc={() =>
86+
!!formContent.jsonTimestamp?.path
87+
? handleJsonPathValidation(formContent.jsonTimestamp?.path)
88+
: null
89+
}
90+
>
91+
{status => (
92+
<Input
93+
type={InputType.Text}
94+
placeholder="eg. $.myJSON.myObject[0].timestampKey"
95+
name="timestamp"
96+
autoFocus={true}
97+
value={formContent.jsonTimestamp?.path}
98+
onChange={e => {
99+
updateForm({
100+
...formContent,
101+
jsonTimestamp: {
102+
...formContent.jsonTimestamp,
103+
path: e.target.value,
104+
},
105+
})
106+
}}
107+
onBlur={() =>
108+
event(
109+
'completed form field',
110+
{formField: 'jsonTimestamp.path'},
111+
{feature: 'subscriptions'}
112+
)
113+
}
114+
testID="timestamp-json-parsing"
115+
status={edit ? status : ComponentStatus.Disabled}
116+
/>
117+
)}
118+
</Form.ValidationElement>
119+
<div className="json-parsing-form__container__dropdown">
120+
<Form.Label label="Timestamp precision" />
121+
<Dropdown
122+
button={(active, onClick) => (
123+
<Dropdown.Button
124+
active={active}
125+
onClick={onClick}
126+
testID="json-timestamp-precision"
127+
status={
128+
edit ? ComponentStatus.Default : ComponentStatus.Disabled
129+
}
130+
>
131+
{formContent.timestampPrecision}
132+
</Dropdown.Button>
133+
)}
134+
menu={onCollapse => (
135+
<Dropdown.Menu onCollapse={onCollapse}>
136+
{Object.keys(PrecisionTypes).map(key => (
137+
<Dropdown.Item
138+
key={key}
139+
id={key}
140+
value={key}
141+
onClick={() => {
142+
event(
143+
'completed form field',
144+
{
145+
formField: 'timestampPrecision',
146+
selected: PrecisionTypes[key],
147+
},
148+
{feature: 'subscriptions'}
149+
)
150+
formContent.timestampPrecision = PrecisionTypes[key]
151+
}}
152+
selected={
153+
formContent.timestampPrecision === PrecisionTypes[key]
154+
}
155+
testID={`json-timestamp-precision-${key}`}
156+
>
157+
{PrecisionTypes[key]}
158+
</Dropdown.Item>
159+
))}
160+
</Dropdown.Menu>
161+
)}
110162
/>
111-
)}
112-
</Form.ValidationElement>
163+
</div>
164+
</FlexBox>
113165
</Grid.Column>
114166
<Grid.Column>
115167
<FlexBox
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
@import '@influxdata/clockface/dist/variables.scss';
22
.line-protocol-form {
3-
&__text {
3+
&__container {
44
margin-top: $cf-space-l;
5-
text-align: center;
6-
color: $cf-grey-95;
5+
margin-bottom: $cf-space-l;
76
}
87
}

src/writeData/subscriptions/components/LineProtocolForm.tsx

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,70 @@
22
import React, {FC} from 'react'
33

44
// Components
5-
import {Grid, Heading, HeadingElement, FontWeight} from '@influxdata/clockface'
5+
import {Grid, Form, Dropdown, ComponentStatus} from '@influxdata/clockface'
6+
7+
// Types
8+
import {Subscription, PrecisionTypes} from 'src/types/subscriptions'
9+
10+
// Utils
11+
import {event} from 'src/cloud/utils/reporting'
612

713
// Styles
814
import 'src/writeData/subscriptions/components/LineProtocolForm.scss'
915

10-
const LineProtocolForm: FC = () => {
11-
// const [lp, setLineProtocol] = useState('')
12-
return (
13-
<div className="line-protocol-form">
14-
<Grid.Column>
15-
<Heading
16-
element={HeadingElement.H5}
17-
weight={FontWeight.Regular}
18-
className="line-protocol-form__text"
19-
>
20-
Great news, Line Protocol doesn’t need additional parsing rules!
21-
</Heading>
22-
{/* For a later iteration */}
23-
{/* <h2 className="form-header">Validate your Line Protocol</h2>
24-
<TextArea
25-
name="validate"
26-
value={lp}
27-
onChange={e => {
28-
setLineProtocol(e.target.value)
29-
}}
30-
style={{height: '146px', minHeight: '146px'}}
31-
ref={null}
32-
maxLength={255}
33-
testID="line-protocol-validate"
34-
placeholder="Enter a line of your data to verify that your formating is valid line protocol."
35-
/> */}
36-
</Grid.Column>
37-
</div>
38-
)
16+
interface Props {
17+
formContent: Subscription
18+
edit: boolean
3919
}
4020

21+
const LineProtocolForm: FC<Props> = ({formContent, edit}) => (
22+
<div className="line-protocol-form">
23+
<Grid.Column>
24+
<div className="line-protocol-form__container">
25+
<Form.Label label="Timestamp precision" />
26+
<Dropdown
27+
button={(active, onClick) => (
28+
<Dropdown.Button
29+
active={active}
30+
onClick={onClick}
31+
testID="lp-timestamp-precision"
32+
status={edit ? ComponentStatus.Default : ComponentStatus.Disabled}
33+
>
34+
{formContent.timestampPrecision}
35+
</Dropdown.Button>
36+
)}
37+
menu={onCollapse => (
38+
<Dropdown.Menu onCollapse={onCollapse}>
39+
{Object.keys(PrecisionTypes).map(key => (
40+
<Dropdown.Item
41+
key={key}
42+
id={key}
43+
value={key}
44+
onClick={() => {
45+
event(
46+
'completed form field',
47+
{
48+
formField: 'timestampPrecision',
49+
selected: PrecisionTypes[key],
50+
},
51+
{feature: 'subscriptions'}
52+
)
53+
formContent.timestampPrecision = PrecisionTypes[key]
54+
}}
55+
selected={
56+
formContent.timestampPrecision === PrecisionTypes[key]
57+
}
58+
testID={`json-timestamp-precision-${key}`}
59+
>
60+
{PrecisionTypes[key]}
61+
</Dropdown.Item>
62+
))}
63+
</Dropdown.Menu>
64+
)}
65+
/>
66+
</div>
67+
</Grid.Column>
68+
</div>
69+
)
70+
4171
export default LineProtocolForm

src/writeData/subscriptions/components/ParsingDetails.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const ParsingDetails: FC<Props> = ({currentSubscription, updateForm, edit}) => (
6161
/>
6262
)}
6363
{currentSubscription.dataFormat === 'lineprotocol' && (
64-
<LineProtocolForm />
64+
<LineProtocolForm edit={edit} formContent={currentSubscription} />
6565
)}
6666
</Grid.Row>
6767
</Grid>

src/writeData/subscriptions/components/ParsingForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const ParsingForm: FC<Props> = ({formContent, updateForm}) =>
5555
className="create"
5656
/>
5757
{formContent.dataFormat === 'lineprotocol' && (
58-
<LineProtocolForm />
58+
<LineProtocolForm edit={true} formContent={formContent} />
5959
)}
6060
{formContent.dataFormat === 'json' && (
6161
<JsonParsingForm

src/writeData/subscriptions/components/StringParsingForm.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,15 @@
3434
margin-bottom: $cf-space-l;
3535
}
3636
}
37+
38+
&__container {
39+
.cf-form--element {
40+
margin-bottom: $cf-space-l;
41+
width: 75%;
42+
}
43+
&__dropdown {
44+
width: 25%;
45+
margin-left: $cf-space-m;
46+
}
47+
}
3748
}

0 commit comments

Comments
 (0)