Skip to content

Commit be60549

Browse files
erkakodiakhq[bot]
andauthored
refactor(ui): improve Yup usage (#2647)
- move creation of validation schemas out of render blocks - use a new validation schema for console context as it isn't a any json object but map[string]string - update Yup to new major version Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent 3643801 commit be60549

File tree

11 files changed

+136
-79
lines changed

11 files changed

+136
-79
lines changed

ui/package-lock.json

+42-43
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"react-router-dom": "^6.21.1",
4040
"tailwind-merge": "^2.2.0",
4141
"uuid": "^9.0.1",
42-
"yup": "^0.32.11"
42+
"yup": "^1.3.3"
4343
},
4444
"devDependencies": {
4545
"@babel/preset-typescript": "^7.23.3",

ui/src/app/console/Console.tsx

+8-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { evaluateURL, evaluateV2 } from '~/data/api';
2020
import { useError } from '~/data/hooks/error';
2121
import { useSuccess } from '~/data/hooks/success';
2222
import {
23-
jsonValidation,
23+
contextValidation,
2424
keyValidation,
2525
requiredValidation
2626
} from '~/data/validations';
@@ -43,6 +43,12 @@ function ResetOnNamespaceChange({ namespace }: { namespace: INamespace }) {
4343
return null;
4444
}
4545

46+
const consoleValidationSchema = Yup.object({
47+
flagKey: keyValidation,
48+
entityId: requiredValidation,
49+
context: contextValidation
50+
});
51+
4652
interface ConsoleFormValues {
4753
flagKey: string;
4854
entityId: string;
@@ -186,11 +192,7 @@ export default function Console() {
186192
<div className="mt-8 w-full overflow-hidden md:w-1/2">
187193
<Formik
188194
initialValues={initialvalues}
189-
validationSchema={Yup.object({
190-
flagKey: keyValidation,
191-
entityId: requiredValidation,
192-
context: jsonValidation
193-
})}
195+
validationSchema={consoleValidationSchema}
194196
onSubmit={(values) => {
195197
handleSubmit(selectedFlag, values);
196198
}}

ui/src/components/flags/FlagForm.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ const flagTypes = [
3535
}
3636
];
3737

38+
const flagValidationSchema = Yup.object({
39+
key: keyValidation,
40+
name: requiredValidation
41+
});
42+
3843
export default function FlagForm(props: { flag?: IFlag }) {
3944
const { flag } = props;
4045

@@ -99,10 +104,7 @@ export default function FlagForm(props: { flag?: IFlag }) {
99104
setSubmitting(false);
100105
});
101106
}}
102-
validationSchema={Yup.object({
103-
key: keyValidation,
104-
name: requiredValidation
105-
})}
107+
validationSchema={flagValidationSchema}
106108
>
107109
{(formik) => {
108110
const { enabled } = formik.values;

ui/src/components/flags/VariantForm.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ import { useSuccess } from '~/data/hooks/success';
1919
import { jsonValidation, keyValidation } from '~/data/validations';
2020
import { IVariant, IVariantBase } from '~/types/Variant';
2121

22+
const variantValidationSchema = Yup.object({
23+
key: keyValidation,
24+
attachment: jsonValidation
25+
});
26+
2227
type VariantFormProps = {
2328
setOpen: (open: boolean) => void;
2429
flagKey: string;
@@ -82,10 +87,7 @@ const VariantForm = forwardRef((props: VariantFormProps, ref: any) => {
8287
setSubmitting(false);
8388
});
8489
}}
85-
validationSchema={Yup.object({
86-
key: keyValidation,
87-
attachment: jsonValidation
88-
})}
90+
validationSchema={variantValidationSchema}
8991
>
9092
{(formik) => (
9193
<Form className="bg-white flex h-full flex-col overflow-y-scroll shadow-xl">

ui/src/components/namespaces/NamespaceForm.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ import { keyValidation, requiredValidation } from '~/data/validations';
1717
import { INamespace, INamespaceBase } from '~/types/Namespace';
1818
import { stringAsKey } from '~/utils/helpers';
1919

20+
const namespaceValidationSchema = Yup.object({
21+
key: keyValidation,
22+
name: requiredValidation
23+
});
24+
2025
type NamespaceFormProps = {
2126
setOpen: (open: boolean) => void;
2227
namespace?: INamespace;
@@ -66,10 +71,7 @@ const NamespaceForm = forwardRef((props: NamespaceFormProps, ref: any) => {
6671
setSubmitting(false);
6772
});
6873
}}
69-
validationSchema={Yup.object({
70-
key: keyValidation,
71-
name: requiredValidation
72-
})}
74+
validationSchema={namespaceValidationSchema}
7375
>
7476
{(formik) => (
7577
<Form className="bg-white flex h-full flex-col overflow-y-scroll shadow-xl">

ui/src/components/rules/forms/RuleForm.tsx

+12-10
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ export const distTypes = [
4545
}
4646
];
4747

48+
const ruleValidationSchema = Yup.object({
49+
segmentKeys: Yup.array()
50+
.of(
51+
Yup.object().shape({
52+
key: keyValidation
53+
})
54+
)
55+
.required()
56+
.min(1)
57+
});
58+
4859
const computePercentages = (n: number): number[] => {
4960
const sum = 100 * 100;
5061

@@ -155,16 +166,7 @@ export default function RuleForm(props: RuleFormProps) {
155166
segmentKeys: initialSegmentKeys,
156167
operator: SegmentOperatorType.OR
157168
}}
158-
validationSchema={Yup.object({
159-
segmentKeys: Yup.array()
160-
.of(
161-
Yup.object().shape({
162-
key: keyValidation
163-
})
164-
)
165-
.required()
166-
.min(1)
167-
})}
169+
validationSchema={ruleValidationSchema}
168170
onSubmit={(values, { setSubmitting }) => {
169171
handleSubmit(values)
170172
.then(() => {

ui/src/components/segments/SegmentForm.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ const segmentMatchTypes = [
3232
}
3333
];
3434

35+
const segmentValidationSchema = Yup.object({
36+
key: keyValidation,
37+
name: requiredValidation
38+
});
39+
3540
type SegmentFormProps = {
3641
segment?: ISegment;
3742
segmentChanged?: () => void;
@@ -98,10 +103,7 @@ export default function SegmentForm(props: SegmentFormProps) {
98103
setSubmitting(false);
99104
});
100105
}}
101-
validationSchema={Yup.object({
102-
key: keyValidation,
103-
name: requiredValidation
104-
})}
106+
validationSchema={segmentValidationSchema}
105107
>
106108
{(formik) => (
107109
<Form className="px-1 sm:overflow-hidden sm:rounded-md">

ui/src/components/tokens/TokenForm.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import { requiredValidation } from '~/data/validations';
1717
import { IAuthTokenBase, IAuthTokenSecret } from '~/types/auth/Token';
1818
import { INamespace } from '~/types/Namespace';
1919

20+
const tokenValidationSchema = Yup.object({
21+
name: requiredValidation
22+
});
23+
2024
type TokenFormProps = {
2125
setOpen: (open: boolean) => void;
2226
onSuccess: (token: IAuthTokenSecret) => void;
@@ -55,9 +59,7 @@ const TokenForm = forwardRef((props: TokenFormProps, ref: any) => {
5559
return (
5660
<Formik
5761
initialValues={initialValues}
58-
validationSchema={Yup.object({
59-
name: requiredValidation
60-
})}
62+
validationSchema={tokenValidationSchema}
6163
onSubmit={(values, { setSubmitting }) => {
6264
let token: IAuthTokenBase = {
6365
name: values.name,

ui/src/data/validation.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { contextValidation } from './validations';
2+
3+
describe('contextValidation', () => {
4+
it('should accept valid input', () => {
5+
const result = contextValidation.isValidSync('{"a":"b", "c":"d"}');
6+
expect(result).toEqual(true);
7+
});
8+
it('should reject arrays', () => {
9+
let result = contextValidation.isValidSync('["a", "b"]');
10+
expect(result).toEqual(false);
11+
result = contextValidation.isValidSync('{"a":["b"]}');
12+
expect(result).toEqual(false);
13+
});
14+
it('should reject simple values', () => {
15+
let result = contextValidation.isValidSync('1');
16+
expect(result).toEqual(false);
17+
result = contextValidation.isValidSync('true');
18+
expect(result).toEqual(false);
19+
});
20+
});

0 commit comments

Comments
 (0)