Skip to content

Commit 00355ff

Browse files
#RI- 5856 - update validation error
1 parent 1536824 commit 00355ff

File tree

7 files changed

+98
-47
lines changed

7 files changed

+98
-47
lines changed

redisinsight/ui/src/pages/rdi/instance/InstancePage.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React, { useEffect, useRef, useState } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
33
import { useHistory, useLocation, useParams } from 'react-router-dom'
44
import { Formik, FormikProps } from 'formik'
5+
import { EuiText } from '@elastic/eui'
6+
import { capitalize } from 'lodash'
57

68
import {
79
appContextSelector,
@@ -22,7 +24,8 @@ import {
2224
setPipelineInitialState,
2325
} from 'uiSrc/slices/rdi/pipeline'
2426
import { IPipeline } from 'uiSrc/slices/interfaces'
25-
import { Nullable, pipelineToJson } from 'uiSrc/utils'
27+
import { createAxiosError, Nullable, pipelineToJson } from 'uiSrc/utils'
28+
import { addErrorNotification } from 'uiSrc/slices/app/notifications'
2629

2730
import InstancePageRouter from './InstancePageRouter'
2831
import { ConfirmLeavePagePopup } from './components'
@@ -88,7 +91,19 @@ const RdiInstancePage = ({ routes = [] }: Props) => {
8891
}, [])
8992

9093
const onSubmit = (values: IPipeline) => {
91-
const JSONValues = pipelineToJson(values)
94+
const JSONValues = pipelineToJson(values, (errors) => {
95+
dispatch(addErrorNotification(createAxiosError({
96+
message: (
97+
<>
98+
<EuiText>{`${capitalize(errors[0].filename)} has an invalid structure.`}</EuiText>
99+
<EuiText>{errors[0].msg}</EuiText>
100+
</>
101+
)
102+
})))
103+
})
104+
if (!JSONValues) {
105+
return
106+
}
92107
dispatch(deployPipelineAction(rdiInstanceId, JSONValues))
93108
}
94109

redisinsight/ui/src/pages/rdi/pipeline-management/pages/config/Config.tsx

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import cx from 'classnames'
66
import { useParams } from 'react-router-dom'
77
import { get, throttle } from 'lodash'
88

9-
import { AxiosError } from 'axios'
109
import { sendPageViewTelemetry, sendEventTelemetry, TelemetryPageView, TelemetryEvent } from 'uiSrc/telemetry'
1110
import { EXTERNAL_LINKS, UTM_MEDIUMS } from 'uiSrc/constants/links'
1211
import { getUtmExternalLink } from 'uiSrc/utils/links'
@@ -17,7 +16,7 @@ import TestConnectionsPanel from 'uiSrc/pages/rdi/pipeline-management/components
1716
import TemplatePopover from 'uiSrc/pages/rdi/pipeline-management/components/template-popover'
1817
import { testConnectionsAction, rdiTestConnectionsSelector, testConnectionsController } from 'uiSrc/slices/rdi/testConnections'
1918
import { appContextPipelineManagement } from 'uiSrc/slices/app/context'
20-
import { isEqualPipelineFile, yamlToJson } from 'uiSrc/utils'
19+
import { createAxiosError, isEqualPipelineFile, yamlToJson } from 'uiSrc/utils'
2120

2221
import { addErrorNotification } from 'uiSrc/slices/app/notifications'
2322
import styles from './styles.module.scss'
@@ -58,22 +57,16 @@ const Config = () => {
5857
}, [isOpenDialog, config, pipelineLoading])
5958

6059
const testConnections = () => {
61-
const onError = (msg: string) => {
62-
dispatch(addErrorNotification({
63-
response: {
64-
data: {
65-
message: (
66-
<>
67-
<EuiText>Config has an invalid structure.</EuiText>
68-
<EuiText>{msg}</EuiText>
69-
</>
70-
)
71-
}
72-
}
73-
} as AxiosError))
74-
}
75-
76-
const JSONValue = yamlToJson(config, onError)
60+
const JSONValue = yamlToJson(config, (msg) => {
61+
dispatch(addErrorNotification(createAxiosError({
62+
message: (
63+
<>
64+
<EuiText>Config has an invalid structure.</EuiText>
65+
<EuiText>{msg}</EuiText>
66+
</>
67+
)
68+
})))
69+
})
7770
if (!JSONValue) {
7871
return
7972
}

redisinsight/ui/src/pages/rdi/pipeline-management/pages/job/Job.tsx

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import React, { useState, useEffect, useRef, useCallback } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
33
import { EuiText, EuiLink, EuiButton, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'
44
import { useFormikContext } from 'formik'
5-
import { get, throttle } from 'lodash'
5+
import { capitalize, get, throttle } from 'lodash'
66
import cx from 'classnames'
77
import { monaco as monacoEditor } from 'react-monaco-editor'
8-
import { AxiosError } from 'axios/index'
98

109
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
1110
import { EXTERNAL_LINKS, UTM_MEDIUMS } from 'uiSrc/constants/links'
@@ -15,7 +14,7 @@ import MonacoYaml from 'uiSrc/components/monaco-editor/components/monaco-yaml'
1514
import DryRunJobPanel from 'uiSrc/pages/rdi/pipeline-management/components/jobs-panel'
1615
import { DSL, KEYBOARD_SHORTCUTS } from 'uiSrc/constants'
1716
import TemplatePopover from 'uiSrc/pages/rdi/pipeline-management/components/template-popover'
18-
import { isEqualPipelineFile, Maybe, yamlToJson } from 'uiSrc/utils'
17+
import { createAxiosError, isEqualPipelineFile, Maybe, yamlToJson } from 'uiSrc/utils'
1918
import { getUtmExternalLink } from 'uiSrc/utils/links'
2019
import { KeyboardShortcut } from 'uiSrc/components'
2120

@@ -69,22 +68,16 @@ const Job = (props: Props) => {
6968
}, [name])
7069

7170
const handleDryRunJob = () => {
72-
const onError = (msg: string) => {
73-
dispatch(addErrorNotification({
74-
response: {
75-
data: {
76-
message: (
77-
<>
78-
<EuiText>{`${name} has an invalid structure.`}</EuiText>
79-
<EuiText>{msg}</EuiText>
80-
</>
81-
)
82-
}
83-
}
84-
} as AxiosError))
85-
}
86-
87-
const JSONValue = yamlToJson(value, onError)
71+
const JSONValue = yamlToJson(value, (msg) => {
72+
dispatch(addErrorNotification(createAxiosError({
73+
message: (
74+
<>
75+
{`${capitalize(name)} has an invalid structure.`}
76+
<EuiText>{msg}</EuiText>
77+
</>
78+
)
79+
})))
80+
})
8881
if (!JSONValue) {
8982
return
9083
}

redisinsight/ui/src/slices/interfaces/app.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ export interface CustomError {
1414
resourceId?: string
1515
}
1616

17+
export interface ErrorOptions {
18+
message: string | JSX.Element
19+
code?: string
20+
config?: object
21+
request?: object
22+
response?: object
23+
}
24+
1725
export interface EnhancedAxiosError extends AxiosError<CustomError> {
1826
}
1927

redisinsight/ui/src/slices/interfaces/rdi.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,8 @@ export interface IStateRdiTestConnections {
233233
export type TJMESPathFunctions = {
234234
[key: string]: Pick<ICommand, 'summary'> & Required<Pick<ICommand, 'arguments'>>
235235
}
236+
237+
export interface IYamlFormatError {
238+
filename: string
239+
msg: string
240+
}

redisinsight/ui/src/utils/apiResponse.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AxiosError } from 'axios'
22
import { first, isArray, get } from 'lodash'
3-
import { AddRedisDatabaseStatus, EnhancedAxiosError, IBulkOperationResult } from 'uiSrc/slices/interfaces'
3+
import { AddRedisDatabaseStatus, EnhancedAxiosError, ErrorOptions, IBulkOperationResult } from 'uiSrc/slices/interfaces'
44
import { parseCustomError } from 'uiSrc/utils'
55

66
export const DEFAULT_ERROR_MESSAGE = 'Something was wrong!'
@@ -12,6 +12,12 @@ export const getAxiosError = (error: EnhancedAxiosError): AxiosError => {
1212
return error
1313
}
1414

15+
export const createAxiosError = (options: ErrorOptions): AxiosError => ({
16+
response: {
17+
data: options
18+
}
19+
} as AxiosError)
20+
1521
export const getApiErrorCode = (error: AxiosError) => error?.response?.status
1622

1723
export function getApiErrorMessage(error: AxiosError): string {

redisinsight/ui/src/utils/transformers/transformRdiPipeline.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
import yaml, { YAMLException } from 'js-yaml'
2-
import { IPipeline, IPipelineJSON, ITargets, TestConnectionStatus, TransformResult } from 'uiSrc/slices/interfaces'
2+
import {
3+
IPipeline,
4+
IPipelineJSON,
5+
ITargets,
6+
IYamlFormatError,
7+
TestConnectionStatus,
8+
TransformResult
9+
} from 'uiSrc/slices/interfaces'
310

411
export const yamlToJson = (value: string, onError: (e: string) => void) => {
512
try {
613
return yaml.load(value) || {}
714
} catch (e) {
815
if (e instanceof YAMLException) {
916
onError(e.reason)
10-
return undefined
1117
}
1218
return undefined
1319
}
@@ -21,13 +27,38 @@ export const pipelineToYaml = (pipeline: IPipelineJSON) => ({
2127
}))
2228
})
2329

24-
export const pipelineToJson = ({ config, jobs }: IPipeline): IPipelineJSON => <IPipelineJSON>({
25-
config: yaml.load(config) || {},
26-
jobs: jobs.reduce<{ [key: string]: unknown }>((acc, job) => {
27-
acc[job.name] = yaml.load(job.value)
30+
export const pipelineToJson = ({ config, jobs }: IPipeline, onError: (errors: IYamlFormatError[]) => void) => {
31+
const result: IPipelineJSON = {
32+
config: {},
33+
jobs: []
34+
}
35+
const errors = []
36+
37+
try {
38+
result.config = yaml.load(config) || {}
39+
} catch (e) {
40+
if (e instanceof YAMLException) {
41+
errors.push({ filename: 'config', msg: e.reason })
42+
}
43+
}
44+
result.jobs = jobs.reduce<{ [key: string]: unknown }>((acc, job) => {
45+
try {
46+
acc[job.name] = yaml.load(job.value)
47+
} catch (e) {
48+
if (e instanceof YAMLException) {
49+
errors.push({ filename: job.name, msg: e.reason })
50+
}
51+
}
2852
return acc
2953
}, {})
30-
})
54+
55+
if (errors.length) {
56+
onError(errors)
57+
return undefined
58+
}
59+
60+
return result
61+
}
3162

3263
export const transformConnectionResults = (sources: ITargets): TransformResult => {
3364
const result: TransformResult = { success: [], fail: [] }

0 commit comments

Comments
 (0)