Skip to content

Commit 7086a2d

Browse files
authored
Merge pull request #210 from PRO-Robotech/feature/dev
Form and Yaml improvements
2 parents e974593 + 62eb30c commit 7086a2d

File tree

15 files changed

+239
-18
lines changed

15 files changed

+239
-18
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@prorobotech/openapi-k8s-toolkit",
3-
"version": "0.0.1-alpha.154",
3+
"version": "0.0.1-alpha.156",
44
"description": "ProRobotech OpenAPI k8s tools",
55
"main": "dist/openapi-k8s-toolkit.cjs.js",
66
"module": "dist/openapi-k8s-toolkit.es.js",

src/components/molecules/BlackholeForm/molecules/FormStringInput/FormStringInput.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint-disable no-nested-ternary */
2-
import React, { FC } from 'react'
3-
import { Flex, Input, Typography, Tooltip, Button } from 'antd'
2+
import React, { FC, useMemo } from 'react'
3+
import { Flex, Input, Typography, Tooltip, Button, Form } from 'antd'
44
import { getStringByName } from 'utils/getStringByName'
5+
import { isMultilineString } from 'utils/isMultilineString'
56
import { TFormName, TPersistedControls } from 'localTypes/form'
67
import { MinusIcon, feedbackIcons } from 'components/atoms'
78
import { PersistedCheckbox, HiddenContainer, ResetedFormItem, CustomSizeTitle } from '../../atoms'
@@ -37,6 +38,11 @@ export const FormStringInput: FC<TFormStringInputProps> = ({
3738
const designNewLayout = useDesignNewLayout()
3839

3940
const fixedName = name === 'nodeName' ? 'nodeNameBecauseOfSuddenBug' : name
41+
const formFieldName = arrName || fixedName
42+
const formValue = Form.useWatch(formFieldName)
43+
44+
// Derive multiline based on current local value
45+
const isMultiline = useMemo(() => isMultilineString(formValue), [formValue])
4046

4147
const title = (
4248
<>
@@ -72,7 +78,11 @@ export const FormStringInput: FC<TFormStringInputProps> = ({
7278
validateTrigger="onBlur"
7379
hasFeedback={designNewLayout ? { icons: feedbackIcons } : true}
7480
>
75-
<Input placeholder={getStringByName(name)} />
81+
<Input.TextArea
82+
placeholder={getStringByName(name)}
83+
rows={isMultiline ? 4 : 1}
84+
autoSize={!isMultiline ? { minRows: 1, maxRows: 1 } : { minRows: 2, maxRows: 10 }}
85+
/>
7686
</ResetedFormItem>
7787
</HiddenContainer>
7888
)

src/components/molecules/BlackholeForm/molecules/YamlEditor/YamlEditor.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@ export const YamlEditor: FC<TYamlEditProps> = ({ theme, currentValues, onChange,
2525
const isApplyingExternalUpdateRef = useRef<boolean>(false)
2626

2727
useEffect(() => {
28-
const next = yaml.stringify(currentValues)
28+
const next = yaml.stringify(currentValues, {
29+
// Use literal block scalar for multiline strings
30+
blockQuote: 'literal',
31+
// Preserve line breaks
32+
lineWidth: 0,
33+
// Use double quotes for strings that need escaping
34+
doubleQuotedAsJSON: false,
35+
})
2936
if (isFocusedRef.current) {
3037
// Defer applying external updates to avoid cursor jumps while typing
3138
pendingExternalYamlRef.current = next ?? ''

src/components/molecules/BlackholeForm/molecules/YamlEditorSingleton/YamlEditorSingleton.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type TYamlEditorSingletonProps = {
2424
designNewLayout?: boolean
2525
designNewLayoutHeight?: number
2626
openNotification?: boolean
27+
readOnly?: boolean
2728
}
2829

2930
export const YamlEditorSingleton: FC<TYamlEditorSingletonProps> = ({
@@ -39,6 +40,7 @@ export const YamlEditorSingleton: FC<TYamlEditorSingletonProps> = ({
3940
designNewLayout,
4041
designNewLayoutHeight,
4142
openNotification,
43+
readOnly = false,
4244
}) => {
4345
const { token } = antdtheme.useToken()
4446
const navigate = useNavigate()
@@ -117,22 +119,27 @@ export const YamlEditorSingleton: FC<TYamlEditorSingletonProps> = ({
117119
height={designNewLayoutHeight || '75vh'}
118120
value={yamlData}
119121
onChange={value => {
120-
setYamlData(value || '')
122+
if (!readOnly) {
123+
setYamlData(value || '')
124+
}
121125
}}
122126
theme={theme === 'dark' ? 'vs-dark' : theme === undefined ? 'vs-dark' : 'vs'}
123127
options={{
124128
theme: theme === 'dark' ? 'vs-dark' : theme === undefined ? 'vs-dark' : 'vs',
129+
readOnly: readOnly,
125130
}}
126131
/>
127132
</Styled.BorderRadiusContainer>
128-
<Styled.ControlsRowContainer $bgColor={token.colorPrimaryBg} $designNewLayout={designNewLayout}>
129-
<Flex gap={designNewLayout ? 10 : 16} align="center">
130-
<Button type="primary" onClick={onSubmit} loading={isLoading}>
131-
Submit
132-
</Button>
133-
{backlink && <Button onClick={() => navigate(backlink)}>Cancel</Button>}
134-
</Flex>
135-
</Styled.ControlsRowContainer>
133+
{!readOnly && (
134+
<Styled.ControlsRowContainer $bgColor={token.colorPrimaryBg} $designNewLayout={designNewLayout}>
135+
<Flex gap={designNewLayout ? 10 : 16} align="center">
136+
<Button type="primary" onClick={onSubmit} loading={isLoading}>
137+
Submit
138+
</Button>
139+
{backlink && <Button onClick={() => navigate(backlink)}>Cancel</Button>}
140+
</Flex>
141+
</Styled.ControlsRowContainer>
142+
)}
136143
{error && (
137144
<Modal
138145
open={!!error}

src/components/molecules/BlackholeForm/organisms/BlackholeForm/BlackholeForm.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ type TBlackholeFormCreateProps = {
6161
hiddenPaths?: string[][]
6262
expandedPaths: string[][]
6363
persistedPaths: string[][]
64+
sortPaths?: string[][]
6465
prefillValuesSchema?: TJSON
6566
prefillValueNamespaceOnly?: string
6667
isNameSpaced?: false | string[]
@@ -87,6 +88,7 @@ export const BlackholeForm: FC<TBlackholeFormCreateProps> = ({
8788
hiddenPaths,
8889
expandedPaths,
8990
persistedPaths,
91+
sortPaths,
9092
prefillValuesSchema,
9193
prefillValueNamespaceOnly,
9294
isNameSpaced,
@@ -1184,6 +1186,7 @@ export const BlackholeForm: FC<TBlackholeFormCreateProps> = ({
11841186
isEdit: !isCreate,
11851187
expandedControls: { onExpandOpen, onExpandClose, expandedKeys },
11861188
persistedControls: { onPersistMark, onPersistUnmark, persistedKeys },
1189+
sortPaths,
11871190
urlParams,
11881191
})}
11891192
</HiddenPathsProvider>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { OpenAPIV2 } from 'openapi-types'
2+
import { TFormName } from 'localTypes/form'
3+
4+
// Function to sort properties based on sortPaths
5+
export const getSortedPropertyKeys = ({
6+
name,
7+
sortPaths,
8+
properties,
9+
}: {
10+
name: TFormName
11+
sortPaths?: string[][]
12+
properties: {
13+
[name: string]: OpenAPIV2.SchemaObject
14+
}
15+
}): (keyof typeof properties)[] => {
16+
if (!sortPaths || sortPaths.length === 0) {
17+
return Object.keys(properties) as (keyof typeof properties)[]
18+
}
19+
20+
const currentPath = Array.isArray(name) ? name : [name]
21+
const currentPathStr = JSON.stringify(currentPath)
22+
23+
// Find sort order for current path
24+
const currentSortPaths = sortPaths.filter(path => {
25+
// For root level (empty array), match paths with single element
26+
if (currentPath.length === 0) {
27+
return path.length === 1
28+
}
29+
30+
// For nested levels, match parent path
31+
const pathStr = JSON.stringify(path.slice(0, -1)) // Remove last element to match parent path
32+
return pathStr === currentPathStr
33+
})
34+
35+
if (currentSortPaths.length === 0) {
36+
return Object.keys(properties) as (keyof typeof properties)[]
37+
}
38+
39+
// Create sort order map
40+
const sortOrder = new Map<string, number>()
41+
currentSortPaths.forEach((path, index) => {
42+
// For root level, use the first element as key
43+
// For nested levels, use the last element as key
44+
const key = currentPath.length === 0 ? path[0] : path[path.length - 1]
45+
sortOrder.set(key, index)
46+
})
47+
48+
// Sort properties based on sort order
49+
return Object.keys(properties).sort((a, b) => {
50+
const aOrder = sortOrder.get(a) ?? Number.MAX_SAFE_INTEGER
51+
const bOrder = sortOrder.get(b) ?? Number.MAX_SAFE_INTEGER
52+
return aOrder - bOrder
53+
}) as (keyof typeof properties)[]
54+
}

src/components/molecules/BlackholeForm/organisms/BlackholeForm/utils.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { TListInputCustomProps, TRangeInputCustomProps } from 'localTypes/formEx
1111
import { TFormName, TExpandedControls, TNamespaceData, TPersistedControls, TUrlParams } from 'localTypes/form'
1212
import { PlusIcon } from 'components/atoms'
1313
import { deepMerge } from 'utils/deepMerge'
14+
import { getSortedPropertyKeys } from './helpers/getSortedPropertyKeys'
1415
import { ResetedFormItem, ArrayInsideContainer, HiddenContainer } from '../../atoms'
1516
import {
1617
FormNamespaceInput,
@@ -321,6 +322,7 @@ export const getArrayFormItemFromSwagger = ({
321322
isEdit,
322323
expandedControls,
323324
persistedControls,
325+
sortPaths,
324326
urlParams,
325327
onRemoveByMinus,
326328
}: {
@@ -354,6 +356,7 @@ export const getArrayFormItemFromSwagger = ({
354356
isEdit: boolean
355357
expandedControls: TExpandedControls
356358
persistedControls: TPersistedControls
359+
sortPaths?: string[][]
357360
urlParams: TUrlParams
358361
onRemoveByMinus?: () => void
359362
}) => {
@@ -524,6 +527,7 @@ export const getArrayFormItemFromSwagger = ({
524527
isEdit,
525528
expandedControls,
526529
persistedControls,
530+
sortPaths,
527531
urlParams,
528532
onRemoveByMinus: () => remove(field.name),
529533
})}
@@ -561,6 +565,7 @@ export const getArrayFormItemFromSwagger = ({
561565
isEdit,
562566
expandedControls,
563567
persistedControls,
568+
sortPaths,
564569
urlParams,
565570
onRemoveByMinus: () => remove(field.name),
566571
})}
@@ -605,6 +610,7 @@ export const getObjectFormItemsDraft = ({
605610
isEdit,
606611
expandedControls,
607612
persistedControls,
613+
sortPaths,
608614
urlParams,
609615
}: {
610616
properties: {
@@ -639,12 +645,12 @@ export const getObjectFormItemsDraft = ({
639645
isEdit: boolean
640646
expandedControls: TExpandedControls
641647
persistedControls: TPersistedControls
648+
sortPaths?: string[][]
642649
urlParams: TUrlParams
643650
}) => {
644651
return (
645652
<HiddenContainer name={name} key={`${arrKey}-${JSON.stringify(name)}`}>
646-
{Object.keys(properties).map((el: keyof typeof properties) => {
647-
// if (properties[el].type === 'object' && properties[el]['x-kubernetes-preserve-unknown-fields']) {
653+
{getSortedPropertyKeys({ name, sortPaths, properties }).map((el: keyof typeof properties) => {
648654
if (properties[el]['x-kubernetes-preserve-unknown-fields']) {
649655
// return <Alert key={String(el)} message="x-kubernetes-preserve-unknown-fields" banner />
650656
const path = Array.isArray(name) ? [...name, String(el)] : [name, String(el)]
@@ -816,6 +822,7 @@ export const getObjectFormItemsDraft = ({
816822
isEdit,
817823
expandedControls,
818824
persistedControls,
825+
sortPaths,
819826
urlParams,
820827
})
821828
}
@@ -848,6 +855,7 @@ export const getObjectFormItemsDraft = ({
848855
isEdit,
849856
expandedControls,
850857
persistedControls,
858+
sortPaths,
851859
urlParams,
852860
})
853861
: undefined
@@ -901,6 +909,7 @@ export const getObjectFormItemsDraft = ({
901909
isEdit,
902910
expandedControls,
903911
persistedControls,
912+
sortPaths,
904913
urlParams,
905914
})
906915
}
@@ -929,6 +938,7 @@ export const getObjectFormItemFromSwagger = ({
929938
isEdit,
930939
expandedControls,
931940
persistedControls,
941+
sortPaths,
932942
urlParams,
933943
onRemoveByMinus,
934944
}: {
@@ -966,6 +976,7 @@ export const getObjectFormItemFromSwagger = ({
966976
isEdit: boolean
967977
expandedControls: TExpandedControls
968978
persistedControls: TPersistedControls
979+
sortPaths?: string[][]
969980
urlParams: TUrlParams
970981
onRemoveByMinus?: () => void
971982
}) => {
@@ -986,6 +997,7 @@ export const getObjectFormItemFromSwagger = ({
986997
isEdit,
987998
expandedControls,
988999
persistedControls,
1000+
sortPaths,
9891001
urlParams,
9901002
})
9911003
return (

src/components/molecules/BlackholeForm/organisms/BlackholeFormDataProvider/BlackholeFormDataProvider.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export const BlackholeFormDataProvider: FC<TBlackholeFormDataProviderProps> = ({
6767
hiddenPaths?: string[][]
6868
expandedPaths: string[][]
6969
persistedPaths: string[][]
70+
sortPaths?: string[][]
7071
kindName: string
7172
isNamespaced?: boolean
7273
isError?: boolean
@@ -108,6 +109,7 @@ export const BlackholeFormDataProvider: FC<TBlackholeFormDataProviderProps> = ({
108109
hiddenPaths: data.hiddenPaths,
109110
expandedPaths: data.expandedPaths || [],
110111
persistedPaths: data.persistedPaths || [],
112+
sortPaths: data.sortPaths,
111113
kindName: data.kindName || '',
112114
formPrefills: data.formPrefills,
113115
namespacesData: data.namespacesData,
@@ -167,6 +169,7 @@ export const BlackholeFormDataProvider: FC<TBlackholeFormDataProviderProps> = ({
167169
hiddenPaths={preparedData.hiddenPaths}
168170
expandedPaths={preparedData.expandedPaths}
169171
persistedPaths={preparedData.persistedPaths}
172+
sortPaths={preparedData.sortPaths}
170173
prefillValuesSchema={data.prefillValuesSchema}
171174
prefillValueNamespaceOnly={data.prefillValueNamespaceOnly}
172175
isCreate={isCreate}

src/components/organisms/DynamicComponents/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export type TDynamicComponentsAppTypeMap = {
118118
typeName: string
119119
prefillValuesRequestIndex: number
120120
substractHeight?: number
121+
readOnly?: boolean
121122
}
122123
VisibilityContainer: {
123124
id: number | string

0 commit comments

Comments
 (0)