argo-cd
128 строк · 4.5 Кб
1import * as React from 'react';
2import {FormApi, NestedForm, Text, Form} from 'react-form';
3import {Checkbox, FormField} from 'argo-ui';
4import {omit} from 'lodash-es';
5import {NumberField} from '../../../shared/components';
6import * as models from '../../../shared/models';
7
8import './application-retry-options.scss';
9
10const durationRegex = /^([\d\.]+[HMS])+$/i;
11const durationRegexError = 'Should be 1h10m10s/10h10m/10m/10s';
12
13const onlyPositiveValidation = {
14min: '1',
15step: '1'
16};
17
18function buildFormItem(label: string, propertyPath: string, component: React.ComponentType, formApi: FormApi, componentProps?: Record<string, any>) {
19return <FormField formApi={formApi} label={label} field={propertyPath} component={component} componentProps={componentProps} />;
20}
21
22const retryOptions: Array<(formApi: FormApi) => React.ReactNode> = [
23formApi => buildFormItem('Limit', 'limit', NumberField, formApi, onlyPositiveValidation),
24formApi => buildFormItem('Duration', 'backoff.duration', Text, formApi),
25formApi => buildFormItem('Max Duration', 'backoff.maxDuration', Text, formApi),
26formApi => buildFormItem('Factor', 'backoff.factor', NumberField, formApi, onlyPositiveValidation)
27];
28
29const defaultInitialValues = {
30limit: 2,
31backoff: {
32duration: '5s',
33maxDuration: '3m0s',
34factor: 2
35}
36};
37
38export const ApplicationRetryForm = ({initValues, field = 'retryStrategy'}: {initValues?: models.RetryStrategy; field: string}) => {
39return (
40<NestedForm field={field}>
41<Form
42defaultValues={{
43...defaultInitialValues,
44...initValues
45}}
46validateError={values => {
47const backoff = values.backoff || {};
48
49if (!values) {
50return {};
51}
52
53return {
54'limit': !values.limit && values.hasOwnProperty('limit') && 'Limit is required',
55
56'backoff.duration':
57backoff.hasOwnProperty('duration') && ((!backoff.duration && 'Duration is required') || (!durationRegex.test(backoff.duration) && durationRegexError)),
58
59'backoff.maxDuration':
60backoff.hasOwnProperty('maxDuration') &&
61((!backoff.maxDuration && 'Max Duration is required') || (!durationRegex.test(backoff.maxDuration) && durationRegexError)),
62
63'backoff.factor': backoff.hasOwnProperty('factor') && !backoff.factor && 'Factor is required'
64};
65}}>
66{nestedFormApi => {
67return (
68<div className='row application-retry-options-list'>
69{retryOptions.map((render, i) => (
70<div className='columns small-6 application-retry-options-list__item' key={i}>
71{render(nestedFormApi)}
72</div>
73))}
74</div>
75);
76}}
77</Form>
78</NestedForm>
79);
80};
81
82export const ApplicationRetryOptions = ({
83formApi,
84initValues,
85field = 'retryStrategy',
86retry,
87setRetry,
88id
89}: {
90formApi: FormApi;
91field?: string;
92initValues?: models.RetryStrategy;
93retry?: boolean;
94setRetry?: (value: boolean) => any;
95id?: string;
96}) => {
97const [retryInternal, setRetryInternal] = React.useState(!!initValues);
98
99const toggleRetry = (value: boolean) => {
100if (!value) {
101const formState = formApi.getFormState();
102const values = formState.values;
103const errors = formState.errors;
104
105const newValues = omit(values, field);
106const newErrors = omit(errors, field);
107
108formApi.setFormState({
109...formState,
110values: newValues,
111errors: newErrors
112});
113}
114if (setRetry != null) {
115setRetry(value);
116} else {
117setRetryInternal(value);
118}
119};
120const isChecked = setRetry != null ? retry : retryInternal;
121return (
122<div className='application-retry-options'>
123<Checkbox id={`retry-${id}`} checked={isChecked} onChange={val => toggleRetry(val)} />
124<label htmlFor={`retry-${id}`}>Retry</label>
125{isChecked && <ApplicationRetryForm initValues={initValues} field={field} />}
126</div>
127);
128};
129