Skip to content

Commit a72e91c

Browse files
committed
Was added create project wizard for oss
1 parent c0ce9cf commit a72e91c

File tree

13 files changed

+582
-210
lines changed

13 files changed

+582
-210
lines changed

frontend/src/locale/en.json

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -209,17 +209,6 @@
209209
"backends_description": "The following backends can be configured with your own cloud credentials in the project settings after the project is created.",
210210
"default_fleet": "Create a default fleet",
211211
"default_fleet_description": "At least one fleet is required to create dev environments, submit tasks, or run services",
212-
"fleet_name": "Name",
213-
"fleet_name_description": "The name of the fleet, e.g. 'my-fleet'",
214-
"fleet_name_placeholder": "Optional",
215-
"fleet_name_constraint": "If not specified, generated automatically",
216-
"fleet_min_instances": "Min number of instances",
217-
"fleet_min_instances_description": "Specify \"0\" if you want instances to be created on demand",
218-
"fleet_max_instances": "Max number of instances",
219-
"fleet_max_instances_description": "Specify it only if you want to limit the maximum number of instances",
220-
"fleet_max_instances_placeholder": "Optional",
221-
"fleet_idle_duration": "Idle duration",
222-
"fleet_idle_duration_description": "For how long instances should be kept idle before termination, e.g. \"0s\", \"1m\", \"1h\"",
223212
"is_public": "Make project public",
224213
"is_public_description": "Public projects can be accessed by any user without being a member",
225214
"backend": "Backend",
@@ -625,6 +614,19 @@
625614
"spot": "Spot",
626615
"started": "Started",
627616
"price": "Price"
617+
},
618+
"edit": {
619+
"name": "Name",
620+
"name_description": "The name of the fleet, e.g. 'my-fleet'",
621+
"name_placeholder": "Optional",
622+
"name_constraint": "If not specified, generated automatically",
623+
"min_instances": "Min number of instances",
624+
"min_instances_description": "Specify \"0\" if you want instances to be created on demand",
625+
"max_instances": "Max number of instances",
626+
"max_instances_description": "Specify it only if you want to limit the maximum number of instances",
627+
"max_instances_placeholder": "Optional",
628+
"idle_duration": "Idle duration",
629+
"idle_duration_description": "For how long instances should be kept idle before termination, e.g. \"0s\", \"1m\", \"1h\""
628630
}
629631
},
630632
"volume": {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React from 'react';
2+
import { get } from 'lodash';
3+
import * as yup from 'yup';
4+
5+
export const FLEET_MIN_INSTANCES_INFO = {
6+
header: <h2>Min number of instances</h2>,
7+
body: (
8+
<>
9+
<p>Some text</p>
10+
</>
11+
),
12+
};
13+
14+
export const FLEET_MAX_INSTANCES_INFO = {
15+
header: <h2>Max number of instances</h2>,
16+
body: (
17+
<>
18+
<p>Some text</p>
19+
</>
20+
),
21+
};
22+
23+
export const FLEET_IDLE_DURATION_INFO = {
24+
header: <h2>Idle duration</h2>,
25+
body: (
26+
<>
27+
<p>Some text</p>
28+
</>
29+
),
30+
};
31+
32+
const requiredFieldError = 'This is required field';
33+
const numberFieldError = 'This is number field';
34+
35+
export const getMinInstancesValidator = (maxInstancesFieldPath: string) =>
36+
yup
37+
.number()
38+
.required(requiredFieldError)
39+
.typeError(numberFieldError)
40+
.min(0)
41+
.test('is-smaller-than-max', 'The minimum value must be less than the maximum value.', (value, context) => {
42+
const maxInstances = get(context.parent, maxInstancesFieldPath);
43+
44+
if (typeof maxInstances !== 'number' || typeof value !== 'number') {
45+
return true;
46+
}
47+
48+
return value <= maxInstances;
49+
});
50+
51+
export const getMaxInstancesValidator = (minInstancesFieldPath: string) =>
52+
yup
53+
.number()
54+
.typeError(numberFieldError)
55+
.min(1)
56+
.test('is-greater-than-min', 'The maximum value must be greater than the minimum value', (value, context) => {
57+
const minInstances = get(context.parent, minInstancesFieldPath);
58+
59+
if (typeof minInstances !== 'number' || typeof value !== 'number') {
60+
return true;
61+
}
62+
63+
return value >= minInstances;
64+
});
65+
66+
export const idleDurationValidator = yup.string().matches(/^[1-9]\d*[smhdw]$/, 'Invalid duration');
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
4+
import { FormInput, InfoLink, SpaceBetween } from 'components';
5+
6+
import { useHelpPanel } from 'hooks';
7+
8+
import { FLEET_IDLE_DURATION_INFO, FLEET_MAX_INSTANCES_INFO, FLEET_MIN_INSTANCES_INFO } from './constants';
9+
import { FleetFormFieldsProps } from './type';
10+
11+
import type { FieldValues } from 'react-hook-form/dist/types/fields';
12+
13+
export function FleetFormFields<T extends FieldValues = FieldValues>({
14+
control,
15+
disabledAllFields,
16+
fieldNamePrefix,
17+
}: FleetFormFieldsProps<T>) {
18+
const { t } = useTranslation();
19+
const [openHelpPanel] = useHelpPanel();
20+
21+
return (
22+
<SpaceBetween direction="vertical" size="l">
23+
<FormInput
24+
label={t('fleets.edit.name')}
25+
description={t('fleets.edit.name_description')}
26+
placeholder={t('fleets.edit.name_placeholder')}
27+
constraintText={t('fleets.edit.name_constraint')}
28+
control={control}
29+
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
30+
// @ts-expect-error
31+
name={`${fieldNamePrefix}.name`}
32+
disabled={disabledAllFields}
33+
/>
34+
35+
<FormInput
36+
info={<InfoLink onFollow={() => openHelpPanel(FLEET_MIN_INSTANCES_INFO)} />}
37+
label={t('fleets.edit.min_instances')}
38+
description={t('fleets.edit.min_instances_description')}
39+
control={control}
40+
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
41+
// @ts-expect-error
42+
name={`${fieldNamePrefix}.min_instances`}
43+
disabled={disabledAllFields}
44+
type="number"
45+
/>
46+
47+
<FormInput
48+
info={<InfoLink onFollow={() => openHelpPanel(FLEET_MAX_INSTANCES_INFO)} />}
49+
label={t('fleets.edit.max_instances')}
50+
description={t('fleets.edit.max_instances_description')}
51+
placeholder={t('fleets.edit.max_instances_placeholder')}
52+
control={control}
53+
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
54+
// @ts-expect-error
55+
name={`${fieldNamePrefix}.max_instances`}
56+
disabled={disabledAllFields}
57+
type="number"
58+
/>
59+
60+
<FormInput
61+
info={<InfoLink onFollow={() => openHelpPanel(FLEET_IDLE_DURATION_INFO)} />}
62+
label={t('fleets.edit.idle_duration')}
63+
description={t('fleets.edit.idle_duration_description')}
64+
control={control}
65+
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
66+
// @ts-expect-error
67+
name={`${fieldNamePrefix}.idle_duration`}
68+
disabled={disabledAllFields}
69+
/>
70+
</SpaceBetween>
71+
);
72+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { FieldValues } from 'react-hook-form/dist/types/fields';
2+
import type { UseFormReturn } from 'react-hook-form/dist/types/form';
3+
4+
export interface FleetFormFieldsProps<TFieldValues extends FieldValues = FieldValues>
5+
extends Pick<UseFormReturn<TFieldValues>, 'control'> {
6+
fieldNamePrefix?: string;
7+
disabledAllFields?: boolean;
8+
}
9+
10+
export type FleetFormFields = {
11+
name?: string;
12+
min_instances: number;
13+
max_instances?: number;
14+
idle_duration?: string;
15+
};

0 commit comments

Comments
 (0)