@devtron-labs/devtron-fe-common-lib 0.0.7-beta-49 → 0.0.7-beta-51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Common/CIPipeline.Types.d.ts +263 -0
- package/dist/Common/Constants.d.ts +5 -0
- package/dist/Common/Dialogs/Types.d.ts +1 -0
- package/dist/Common/Helper.d.ts +0 -22
- package/dist/Common/Types.d.ts +28 -2
- package/dist/Common/index.d.ts +1 -1
- package/dist/index.js +101 -212
- package/package.json +1 -1
- package/src/Assets/Icon/ic-help.svg +3 -0
- package/src/Common/CIPipeline.Types.ts +275 -0
- package/src/Common/Constants.ts +6 -0
- package/src/Common/Dialogs/DeleteDialog.tsx +45 -27
- package/src/Common/Dialogs/Types.ts +1 -0
- package/src/Common/Helper.tsx +36 -199
- package/src/Common/TippyCustomized.tsx +28 -2
- package/src/Common/Types.ts +30 -2
- package/src/Common/index.ts +1 -1
- package/dist/Common/DeleteComponentModal/DeleteComponent.d.ts +0 -4
- package/dist/Common/DeleteComponentModal/types.d.ts +0 -15
- package/src/Assets/Icon/ic-info-filled.svg +0 -7
- package/src/Assets/Icon/ic-warning.svg +0 -7
- package/src/Common/DeleteComponentModal/DeleteComponent.tsx +0 -95
- package/src/Common/DeleteComponentModal/types.ts +0 -15
- /package/src/Assets/Img/{warning-medium.svg → delete-medium.svg} +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
export interface MaterialType {
|
|
2
|
+
name: string
|
|
3
|
+
type: string
|
|
4
|
+
value: string
|
|
5
|
+
gitMaterialId: number
|
|
6
|
+
id: number
|
|
7
|
+
isSelected: boolean
|
|
8
|
+
gitHostId: number
|
|
9
|
+
gitProviderId: number
|
|
10
|
+
regex?: string
|
|
11
|
+
isRegex: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Githost {
|
|
15
|
+
id: number
|
|
16
|
+
name: string
|
|
17
|
+
active: boolean
|
|
18
|
+
webhookSecret: string
|
|
19
|
+
webhookUrl: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WebhookEvent {
|
|
23
|
+
id: number
|
|
24
|
+
gitHostId: number
|
|
25
|
+
name: string
|
|
26
|
+
isActive: boolean
|
|
27
|
+
selectors: WebhookEventSelectors[]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface WebhookEventSelectors {
|
|
31
|
+
id: number
|
|
32
|
+
eventId: number
|
|
33
|
+
name: string
|
|
34
|
+
selector: string
|
|
35
|
+
toShowInCiFilter: boolean
|
|
36
|
+
fixValue: string
|
|
37
|
+
toShow: boolean
|
|
38
|
+
possibleValues: string
|
|
39
|
+
isActive: boolean
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CiPipelineSourceTypeOption {
|
|
43
|
+
label: string
|
|
44
|
+
value: string
|
|
45
|
+
isDisabled: boolean
|
|
46
|
+
isSelected: boolean
|
|
47
|
+
isWebhook: boolean
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export enum RefVariableType {
|
|
51
|
+
GLOBAL = 'GLOBAL',
|
|
52
|
+
FROM_PREVIOUS_STEP = 'FROM_PREVIOUS_STEP',
|
|
53
|
+
NEW = 'NEW',
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export enum PluginType {
|
|
57
|
+
INLINE = 'INLINE',
|
|
58
|
+
PLUGIN_REF = 'REF_PLUGIN',
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export enum ScriptType {
|
|
62
|
+
SHELL = 'SHELL',
|
|
63
|
+
DOCKERFILE = 'DOCKERFILE',
|
|
64
|
+
CONTAINERIMAGE = 'CONTAINER_IMAGE',
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export enum MountPath {
|
|
68
|
+
TRUE = 'Yes',
|
|
69
|
+
FALSE = 'No',
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export enum ConditionType {
|
|
73
|
+
SKIP = 'SKIP',
|
|
74
|
+
TRIGGER = 'TRIGGER',
|
|
75
|
+
PASS = 'PASS',
|
|
76
|
+
FAIL = 'FAIL',
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export enum RefVariableStageType {
|
|
80
|
+
PRE_CI = 'PRE_CI',
|
|
81
|
+
POST_CI = 'POST_CI',
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface VariableType {
|
|
85
|
+
id: number
|
|
86
|
+
name: string
|
|
87
|
+
value: string
|
|
88
|
+
format: string
|
|
89
|
+
description: string
|
|
90
|
+
defaultValue: string
|
|
91
|
+
variableType: RefVariableType
|
|
92
|
+
refVariableStepIndex: number
|
|
93
|
+
refVariableName: string
|
|
94
|
+
refVariableStage?: RefVariableStageType
|
|
95
|
+
variableStepIndexInPlugin?: number
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface CommandArgsMap {
|
|
99
|
+
command: string
|
|
100
|
+
args: string[]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface PortMapType {
|
|
104
|
+
portOnLocal: number
|
|
105
|
+
portOnContainer: number
|
|
106
|
+
}
|
|
107
|
+
interface ConditionDetails {
|
|
108
|
+
id: number
|
|
109
|
+
conditionOnVariable: string
|
|
110
|
+
conditionOperator: string
|
|
111
|
+
conditionType: ConditionType
|
|
112
|
+
conditionalValue: string
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface InlineStepDetailType {
|
|
116
|
+
scriptType: ScriptType
|
|
117
|
+
isMountCustomScript?: boolean
|
|
118
|
+
script?: string
|
|
119
|
+
dockerFileExists?: boolean
|
|
120
|
+
mountPath?: string
|
|
121
|
+
mountCodeToContainer?: boolean
|
|
122
|
+
mountDirectoryFromHost?: boolean
|
|
123
|
+
containerImagePath?: string
|
|
124
|
+
imagePullSecret?: string
|
|
125
|
+
commandArgsMap?: CommandArgsMap[]
|
|
126
|
+
portMap?: PortMapType[]
|
|
127
|
+
mountPathMap?: {
|
|
128
|
+
filePathOnDisk: string
|
|
129
|
+
filePathOnContainer: string
|
|
130
|
+
}[]
|
|
131
|
+
inputVariables?: VariableType[]
|
|
132
|
+
outputVariables?: VariableType[]
|
|
133
|
+
conditionDetails: ConditionDetails[]
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
interface PluginRefStepDetailType {
|
|
137
|
+
id: number
|
|
138
|
+
pluginId: number
|
|
139
|
+
inputVariables?: VariableType[]
|
|
140
|
+
outputVariables?: VariableType[]
|
|
141
|
+
conditionDetails?: ConditionDetails[]
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface StepType {
|
|
145
|
+
id: number
|
|
146
|
+
index: number
|
|
147
|
+
name: string
|
|
148
|
+
description: string
|
|
149
|
+
stepType: PluginType
|
|
150
|
+
outputDirectoryPath: string[]
|
|
151
|
+
inlineStepDetail?: InlineStepDetailType
|
|
152
|
+
pluginRefStepDetail?: PluginRefStepDetailType
|
|
153
|
+
triggerIfParentStageFail: boolean
|
|
154
|
+
isMandatory?: boolean
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface BuildStageType {
|
|
158
|
+
id: number
|
|
159
|
+
steps: StepType[]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export enum CIBuildType {
|
|
163
|
+
SELF_DOCKERFILE_BUILD_TYPE = 'self-dockerfile-build',
|
|
164
|
+
MANAGED_DOCKERFILE_BUILD_TYPE = 'managed-dockerfile-build',
|
|
165
|
+
BUILDPACK_BUILD_TYPE = 'buildpack-build',
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface BuildPackConfigType {
|
|
169
|
+
builderId: string
|
|
170
|
+
language: string
|
|
171
|
+
languageVersion: string
|
|
172
|
+
projectPath: string
|
|
173
|
+
builderLangEnvParam?: string
|
|
174
|
+
currentBuilderLangEnvParam?: string
|
|
175
|
+
buildPacks?: any
|
|
176
|
+
args?: Record<string, string>
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface DockerBuildConfigType {
|
|
180
|
+
dockerfileContent: string
|
|
181
|
+
dockerfileRelativePath: string
|
|
182
|
+
buildContext: string
|
|
183
|
+
dockerfilePath?: string
|
|
184
|
+
dockerfileRepository?: string
|
|
185
|
+
args?: Record<string, string>
|
|
186
|
+
targetPlatform?: any
|
|
187
|
+
language?: string
|
|
188
|
+
languageFramework?: string
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface CIBuildConfigType {
|
|
192
|
+
buildPackConfig: BuildPackConfigType
|
|
193
|
+
ciBuildType: CIBuildType
|
|
194
|
+
dockerBuildConfig: DockerBuildConfigType
|
|
195
|
+
gitMaterialId: number
|
|
196
|
+
buildContextGitMaterialId: number
|
|
197
|
+
id?: number
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export interface DockerConfigOverrideType {
|
|
201
|
+
dockerRegistry: string
|
|
202
|
+
dockerRepository: string
|
|
203
|
+
ciBuildConfig: CIBuildConfigType
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export interface FormType {
|
|
207
|
+
name: string
|
|
208
|
+
args: { key: string; value: string }[]
|
|
209
|
+
materials: MaterialType[]
|
|
210
|
+
gitHost: Githost
|
|
211
|
+
webhookEvents: WebhookEvent[]
|
|
212
|
+
ciPipelineSourceTypeOptions: CiPipelineSourceTypeOption[]
|
|
213
|
+
webhookConditionList: { selectorId: number; value: string }[]
|
|
214
|
+
triggerType: string
|
|
215
|
+
scanEnabled?: boolean
|
|
216
|
+
beforeDockerBuildScripts?: {
|
|
217
|
+
id: number
|
|
218
|
+
name: string
|
|
219
|
+
outputLocation: string
|
|
220
|
+
script: string
|
|
221
|
+
isCollapsed: boolean
|
|
222
|
+
index: number
|
|
223
|
+
}[]
|
|
224
|
+
afterDockerBuildScripts?: {
|
|
225
|
+
id: number
|
|
226
|
+
name: string
|
|
227
|
+
outputLocation: string
|
|
228
|
+
script: string
|
|
229
|
+
isCollapsed: boolean
|
|
230
|
+
index: number
|
|
231
|
+
}[]
|
|
232
|
+
ciPipelineEditable: true
|
|
233
|
+
preBuildStage?: BuildStageType
|
|
234
|
+
postBuildStage?: BuildStageType
|
|
235
|
+
isDockerConfigOverridden?: boolean
|
|
236
|
+
dockerConfigOverride?: DockerConfigOverrideType
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface ErrorObj {
|
|
240
|
+
isValid: boolean
|
|
241
|
+
message: string | null
|
|
242
|
+
}
|
|
243
|
+
export interface TaskErrorObj {
|
|
244
|
+
isValid: boolean
|
|
245
|
+
name: ErrorObj
|
|
246
|
+
inlineStepDetail?: { inputVariables?: ErrorObj[]; outputVariables?: ErrorObj[] }
|
|
247
|
+
pluginRefStepDetail?: { inputVariables?: ErrorObj[]; outputVariables?: ErrorObj[] }
|
|
248
|
+
}
|
|
249
|
+
export interface FormErrorObjectType {
|
|
250
|
+
name: ErrorObj
|
|
251
|
+
materials?: MaterialType[]
|
|
252
|
+
preBuildStage?: {
|
|
253
|
+
isValid: boolean
|
|
254
|
+
steps: TaskErrorObj[]
|
|
255
|
+
}
|
|
256
|
+
buildStage?: {
|
|
257
|
+
isValid: boolean
|
|
258
|
+
name: ErrorObj
|
|
259
|
+
}
|
|
260
|
+
postBuildStage?: {
|
|
261
|
+
isValid: boolean
|
|
262
|
+
steps: TaskErrorObj[]
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export interface PluginDetailType {
|
|
267
|
+
id: number
|
|
268
|
+
name: string
|
|
269
|
+
type: string
|
|
270
|
+
description: string
|
|
271
|
+
icon: string
|
|
272
|
+
tags: string[]
|
|
273
|
+
inputVariables?: VariableType[]
|
|
274
|
+
outputVariables?: VariableType[]
|
|
275
|
+
}
|
package/src/Common/Constants.ts
CHANGED
|
@@ -57,4 +57,10 @@ export const TOKEN_COOKIE_NAME = 'argocd.token'
|
|
|
57
57
|
export const TriggerTypeMap = {
|
|
58
58
|
automatic: 'Auto',
|
|
59
59
|
manual: 'Manual',
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const BuildStageVariable = {
|
|
63
|
+
PreBuild: 'preBuildStage',
|
|
64
|
+
Build: 'buildStage',
|
|
65
|
+
PostBuild: 'postBuildStage',
|
|
60
66
|
}
|
|
@@ -1,35 +1,53 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import warn from '../../Assets/Img/
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import warn from '../../Assets/Img/delete-medium.svg'
|
|
3
3
|
import { Progressing } from '../Progressing'
|
|
4
|
-
import ConfirmationDialog from './ConfirmationDialog'
|
|
5
|
-
import { DeleteDialogProps } from './Types'
|
|
4
|
+
import ConfirmationDialog from './ConfirmationDialog'
|
|
5
|
+
import { DeleteDialogProps } from './Types'
|
|
6
6
|
|
|
7
7
|
export const DeleteDialog: React.FC<DeleteDialogProps> & { Description?: React.FC<any> } = function (props) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
8
|
+
return (
|
|
9
|
+
<ConfirmationDialog className="confirmation-dialog__body--w-400">
|
|
10
|
+
<ConfirmationDialog.Icon src={warn} />
|
|
11
|
+
<ConfirmationDialog.Body title={props.title}>
|
|
12
|
+
<div className="fs-13 cn-7 lh-1-54 w-100">
|
|
13
|
+
{props.description ? props.description : null}
|
|
14
|
+
{props.children}
|
|
15
|
+
</div>
|
|
16
|
+
</ConfirmationDialog.Body>
|
|
17
|
+
<ConfirmationDialog.ButtonGroup>
|
|
18
|
+
<div className="flex right">
|
|
19
|
+
<button
|
|
20
|
+
type="button"
|
|
21
|
+
className="cta cancel cta-cd-delete-modal ml-16"
|
|
22
|
+
onClick={props.closeDelete}
|
|
23
|
+
disabled={props.apiCallInProgress}
|
|
24
|
+
data-testid="dialog-cancel"
|
|
25
|
+
>
|
|
26
|
+
Cancel
|
|
27
|
+
</button>
|
|
28
|
+
<button
|
|
29
|
+
type="button"
|
|
30
|
+
className="cta delete cta-cd-delete-modal ml-16"
|
|
31
|
+
onClick={() => props.delete()}
|
|
32
|
+
disabled={props.apiCallInProgress}
|
|
33
|
+
data-testid="dialog-delete"
|
|
34
|
+
>
|
|
35
|
+
{props.apiCallInProgress ? (
|
|
36
|
+
<Progressing />
|
|
37
|
+
) : (
|
|
38
|
+
`${props.deletePrefix || ''}${
|
|
39
|
+
props.buttonPrimaryText ? props.buttonPrimaryText : 'Delete'
|
|
40
|
+
}${props.deletePostfix || ''}`
|
|
41
|
+
)}
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
</ConfirmationDialog.ButtonGroup>
|
|
45
|
+
</ConfirmationDialog>
|
|
46
|
+
)
|
|
26
47
|
}
|
|
27
48
|
|
|
28
49
|
function DeleteDialogDescription(props) {
|
|
29
|
-
|
|
30
|
-
return <>
|
|
31
|
-
{props.children}
|
|
32
|
-
</>
|
|
50
|
+
return <>{props.children}</>
|
|
33
51
|
}
|
|
34
52
|
|
|
35
|
-
DeleteDialog.Description = DeleteDialogDescription
|
|
53
|
+
DeleteDialog.Description = DeleteDialogDescription
|
package/src/Common/Helper.tsx
CHANGED
|
@@ -1,49 +1,48 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect, useRef } from 'react'
|
|
2
2
|
import { ServerErrors } from './ServerError'
|
|
3
3
|
import { toast } from 'react-toastify'
|
|
4
4
|
import * as Sentry from '@sentry/browser'
|
|
5
5
|
import { toastAccessDenied } from './ToastBody'
|
|
6
6
|
import { ERROR_EMPTY_SCREEN, TOKEN_COOKIE_NAME } from './Constants'
|
|
7
|
-
import { ReactComponent as FormError } from '../Assets/Icon/ic-warning.svg'
|
|
8
7
|
|
|
9
8
|
toast.configure({
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
autoClose: 3000,
|
|
10
|
+
hideProgressBar: true,
|
|
11
|
+
pauseOnHover: true,
|
|
12
|
+
pauseOnFocusLoss: true,
|
|
13
|
+
closeOnClick: false,
|
|
14
|
+
newestOnTop: true,
|
|
15
|
+
toastClassName: 'devtron-toast',
|
|
16
|
+
bodyClassName: 'devtron-toast__body',
|
|
18
17
|
})
|
|
19
18
|
|
|
20
19
|
export function showError(serverError, showToastOnUnknownError = true, hideAccessError = false) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
if (serverError instanceof ServerErrors && Array.isArray(serverError.errors)) {
|
|
21
|
+
serverError.errors.map(({ userMessage, internalMessage }) => {
|
|
22
|
+
if (
|
|
23
|
+
serverError.code === 403 &&
|
|
24
|
+
(userMessage === ERROR_EMPTY_SCREEN.UNAUTHORIZED || userMessage === ERROR_EMPTY_SCREEN.FORBIDDEN)
|
|
25
|
+
) {
|
|
26
|
+
if (!hideAccessError) {
|
|
27
|
+
toastAccessDenied()
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
toast.error(userMessage || internalMessage)
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
} else {
|
|
34
|
+
if (serverError.code !== 403 && serverError.code !== 408) {
|
|
35
|
+
Sentry.captureException(serverError)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (showToastOnUnknownError) {
|
|
39
|
+
if (serverError.message) {
|
|
40
|
+
toast.error(serverError.message)
|
|
41
|
+
} else {
|
|
42
|
+
toast.error('Some Error Occurred')
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
interface ConditionalWrapper<T> {
|
|
@@ -168,166 +167,4 @@ export function getLoginInfo() {
|
|
|
168
167
|
return null
|
|
169
168
|
}
|
|
170
169
|
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function useForm(stateSchema, validationSchema = {}, callback) {
|
|
174
|
-
const [state, setState] = useState(stateSchema)
|
|
175
|
-
const [disable, setDisable] = useState(true)
|
|
176
|
-
const [isDirty, setIsDirty] = useState(false)
|
|
177
|
-
|
|
178
|
-
// Disable button in initial render.
|
|
179
|
-
useEffect(() => {
|
|
180
|
-
setDisable(true)
|
|
181
|
-
}, [])
|
|
182
|
-
|
|
183
|
-
// For every changed in our state this will be fired
|
|
184
|
-
// To be able to disable the button
|
|
185
|
-
useEffect(() => {
|
|
186
|
-
if (isDirty) {
|
|
187
|
-
setDisable(validateState(state))
|
|
188
|
-
}
|
|
189
|
-
}, [state, isDirty])
|
|
190
|
-
|
|
191
|
-
// Used to disable submit button if there's an error in state
|
|
192
|
-
// or the required field in state has no value.
|
|
193
|
-
// Wrapped in useCallback to cached the function to avoid intensive memory leaked
|
|
194
|
-
// in every re-render in component
|
|
195
|
-
const validateState = useCallback(
|
|
196
|
-
(state) => {
|
|
197
|
-
//check errors in all fields
|
|
198
|
-
const hasErrorInState = Object.keys(validationSchema).some((key) => {
|
|
199
|
-
const isInputFieldRequired = validationSchema[key].required
|
|
200
|
-
const stateValue = state[key].value // state value
|
|
201
|
-
const stateError = state[key].error // state error
|
|
202
|
-
return (isInputFieldRequired && !stateValue) || stateError
|
|
203
|
-
})
|
|
204
|
-
return hasErrorInState
|
|
205
|
-
},
|
|
206
|
-
[state, validationSchema],
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
function validateField(name, value): string | string[] {
|
|
210
|
-
if (validationSchema[name].required) {
|
|
211
|
-
if (!value) {
|
|
212
|
-
return 'This is a required field.'
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function _validateSingleValidator(validator, value) {
|
|
217
|
-
if (value && !validator.regex.test(value)) {
|
|
218
|
-
return false
|
|
219
|
-
}
|
|
220
|
-
return true
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// single validator
|
|
224
|
-
let _validator = validationSchema[name].validator
|
|
225
|
-
if (_validator && typeof _validator === 'object') {
|
|
226
|
-
if (!_validateSingleValidator(_validator, value)) {
|
|
227
|
-
return _validator.error
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// multiple validators
|
|
232
|
-
let _validators = validationSchema[name].validators
|
|
233
|
-
if (_validators && typeof _validators === 'object' && Array.isArray(_validators)) {
|
|
234
|
-
let errors = []
|
|
235
|
-
_validators.forEach((_validator) => {
|
|
236
|
-
if (!_validateSingleValidator(_validator, value)) {
|
|
237
|
-
errors.push(_validator.error)
|
|
238
|
-
}
|
|
239
|
-
})
|
|
240
|
-
if (errors.length > 0) {
|
|
241
|
-
return errors
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return ''
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const handleOnChange = useCallback(
|
|
249
|
-
(event) => {
|
|
250
|
-
setIsDirty(true)
|
|
251
|
-
|
|
252
|
-
const { name, value } = event.target
|
|
253
|
-
let error = validateField(name, value)
|
|
254
|
-
setState((prevState) => ({
|
|
255
|
-
...prevState,
|
|
256
|
-
[name]: { value, error },
|
|
257
|
-
}))
|
|
258
|
-
},
|
|
259
|
-
[validationSchema],
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
const handleOnSubmit = (event) => {
|
|
263
|
-
event.preventDefault()
|
|
264
|
-
const newState = Object.keys(validationSchema).reduce((agg, curr) => {
|
|
265
|
-
agg[curr] = { ...state[curr], error: validateField(curr, state[curr].value) }
|
|
266
|
-
return agg
|
|
267
|
-
}, state)
|
|
268
|
-
if (!validateState(newState)) {
|
|
269
|
-
callback(state)
|
|
270
|
-
} else {
|
|
271
|
-
setState({ ...newState })
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
return { state, disable, handleOnChange, handleOnSubmit }
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function handleError(error: any): any[] {
|
|
278
|
-
if (!error) {
|
|
279
|
-
return []
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (!Array.isArray(error)) {
|
|
283
|
-
return [error]
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
return error
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export function CustomInput({
|
|
290
|
-
name,
|
|
291
|
-
value,
|
|
292
|
-
error,
|
|
293
|
-
onChange,
|
|
294
|
-
onBlur = (e) => {},
|
|
295
|
-
onFocus = (e) => {},
|
|
296
|
-
label,
|
|
297
|
-
type = 'text',
|
|
298
|
-
disabled = false,
|
|
299
|
-
autoComplete = 'off',
|
|
300
|
-
labelClassName = '',
|
|
301
|
-
placeholder = '',
|
|
302
|
-
tabIndex = 1,
|
|
303
|
-
dataTestid = '',
|
|
304
|
-
}) {
|
|
305
|
-
return (
|
|
306
|
-
<div className="flex column left top">
|
|
307
|
-
<label className={`form__label ${labelClassName}`}>{label}</label>
|
|
308
|
-
<input
|
|
309
|
-
data-testid={dataTestid}
|
|
310
|
-
type={type}
|
|
311
|
-
name={name}
|
|
312
|
-
autoComplete="off"
|
|
313
|
-
className="form__input"
|
|
314
|
-
onChange={(e) => {
|
|
315
|
-
e.persist()
|
|
316
|
-
onChange(e)
|
|
317
|
-
}}
|
|
318
|
-
onBlur={onBlur}
|
|
319
|
-
onFocus={onFocus}
|
|
320
|
-
placeholder={placeholder}
|
|
321
|
-
value={value}
|
|
322
|
-
disabled={disabled}
|
|
323
|
-
tabIndex={tabIndex}
|
|
324
|
-
/>
|
|
325
|
-
{handleError(error).map((err) => (
|
|
326
|
-
<div className="form__error">
|
|
327
|
-
<FormError className="form__icon form__icon--error" />
|
|
328
|
-
{err}
|
|
329
|
-
</div>
|
|
330
|
-
))}
|
|
331
|
-
</div>
|
|
332
|
-
)
|
|
333
|
-
}
|
|
170
|
+
}
|