-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
【GLCC】Higress Console 支持通过表单配置 Wasm 插件 #322
Merged
Merged
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
1aec989
forms
guluguluhhhh 183cb9e
form2
guluguluhhhh 9d89615
form-3
guluguluhhhh 5be1ee4
forms-4
551a282
update misc
35b6e49
fix_getLocalizedText
5ea8585
merge form and tab into Detail
7e5b126
Update GlobalPluginDetail.tsx
guluguluhhhh 1f1c7ef
fix coverProblem
63a86ae
Merge branch 'main' of https://github.com/guluguluhhhh/higress-consol…
32b61c8
update GlobalPluginDetail.tsx
e38262f
fix mergeProblem
fadfb0e
fix some problems
899b12c
fix function getLocalizedText
440457e
fix lots of bugs
4211ef2
fix several bugs
4a014e6
stringify
55cc52c
else if
3456239
add key
33de91e
fix validation rules
adbd91d
Merge branch 'main' into main
CH3CHO 2ff06b3
Delete package-lock.json
guluguluhhhh 02299c7
Delete package.json
guluguluhhhh 448ea9b
fix lint
9090e47
Merge branch 'main' of https://github.com/guluguluhhhh/higress-consol…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.factor :global { | ||
.ant-empty-normal { | ||
margin: 0; | ||
} | ||
} |
222 changes: 222 additions & 0 deletions
222
frontend/src/pages/plugin/components/PluginDrawer/ArrayForm/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'; | ||
import { Button, Form, Input, Select, Table } from 'antd'; | ||
import type { FormInstance } from 'antd/es/form'; | ||
import { uniqueId } from 'lodash'; | ||
import React, { useContext, useEffect, useRef, useState } from 'react'; | ||
import { useTranslation } from 'react-i18next'; | ||
import styles from './index.module.css'; | ||
import i18next from 'i18next'; | ||
|
||
const EditableContext = React.createContext<FormInstance<any> | null>(null); | ||
|
||
interface Item { | ||
key: string; | ||
} | ||
|
||
interface EditableRowProps { | ||
index: number; | ||
} | ||
|
||
const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => { | ||
const [form] = Form.useForm(); | ||
return ( | ||
<Form form={form} component={false}> | ||
<EditableContext.Provider value={form}> | ||
<tr {...props} /> | ||
</EditableContext.Provider> | ||
</Form> | ||
); | ||
}; | ||
|
||
interface EditableCellProps { | ||
title: React.ReactNode; | ||
editable: boolean; | ||
children: React.ReactNode; | ||
dataIndex: keyof Item; | ||
record: Item; | ||
nodeType: 'select' | 'input'; | ||
handleSave: (record: Item) => void; | ||
} | ||
|
||
const EditableCell: React.FC<EditableCellProps> = ({ | ||
title, | ||
editable, | ||
children, | ||
dataIndex, | ||
nodeType, | ||
record, | ||
handleSave, | ||
...restProps | ||
}) => { | ||
const { t } = useTranslation(); | ||
const [editing, setEditing] = useState(true); | ||
const inputRef = useRef(null); | ||
const form = useContext(EditableContext)!; | ||
|
||
const matchOptions = ['PRE', 'EQUAL', 'REGULAR'].map((v) => { | ||
return { label: t(`route.matchTypes.${v}`), value: v }; | ||
}); | ||
|
||
useEffect(() => { | ||
form.setFieldsValue({ ...record }); | ||
}, [editing]); | ||
|
||
const save = async () => { | ||
try { | ||
const values = await form.validateFields(); | ||
handleSave({ ...record, ...values }); | ||
} catch (errInfo) { | ||
console.error('Save failed: ', errInfo); | ||
} | ||
}; | ||
|
||
let childNode = children; | ||
|
||
const node = <Input ref={inputRef} onPressEnter={save} onBlur={save} /> | ||
|
||
if (editable) { | ||
childNode = ( | ||
<Form.Item | ||
style={{ margin: 0 }} | ||
name={dataIndex} | ||
rules={[ | ||
{ | ||
required: true, | ||
}, | ||
]} | ||
> | ||
{node} | ||
</Form.Item> | ||
); | ||
} | ||
|
||
return <td {...restProps}>{childNode}</td>; | ||
}; | ||
|
||
type EditableTableProps = Parameters<typeof Table>[0]; | ||
|
||
interface DataType { | ||
uid: number; | ||
} | ||
|
||
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>; | ||
|
||
const ArrayForm: React.FC = ({ array, value, onChange }) => { | ||
const { t } = useTranslation(); | ||
|
||
const initDataSource = value || []; | ||
for (const item of initDataSource) { | ||
if (!item.uid) { | ||
item.uid = uniqueId(); | ||
} | ||
} | ||
|
||
const [dataSource, setDataSource] = useState<DataType[]>(value || []); | ||
|
||
function getLocalizedText(obj: any, index: string, key: string) { | ||
const i18nObj = obj[`x-${index}-i18n`]; | ||
if(i18next.language === 'en-US') return i18nObj && i18nObj[i18next.language] || key || ''; | ||
else return i18nObj && i18nObj[i18next.language] || obj[index] || ''; | ||
} | ||
|
||
const defaultColumns: any[] = []; | ||
if (array.type === 'object') { | ||
Object.entries(array.properties).forEach(([key, prop]) => { | ||
let translatedTitle = getLocalizedText(prop, 'title', key); | ||
const isRequired = (array.required || []).includes(key); | ||
defaultColumns.push({ | ||
title: translatedTitle, | ||
dataIndex: key, | ||
editable: true, | ||
required: isRequired, | ||
}); | ||
}); | ||
} else { | ||
defaultColumns.push({ | ||
title: t(array.title), | ||
dataIndex: 'Item', | ||
editable: true, | ||
}); | ||
} | ||
|
||
defaultColumns.push({ | ||
dataIndex: 'operation', | ||
width: 60, | ||
render: (_, record: { uid: number }) => | ||
(dataSource.length >= 1 ? ( | ||
<div onClick={() => handleDelete(record.uid)}> | ||
<DeleteOutlined /> | ||
</div> | ||
) : null), | ||
}); | ||
|
||
const handleAdd = () => { | ||
const newData: DataType = { | ||
uid: uniqueId(), | ||
}; | ||
setDataSource([...dataSource, newData]); | ||
onChange([...dataSource, newData]); | ||
}; | ||
|
||
const handleDelete = (uid: number) => { | ||
const newData = dataSource.filter((item) => item.uid !== uid); | ||
setDataSource(newData); | ||
onChange(newData); | ||
}; | ||
|
||
const handleSave = (row: DataType) => { | ||
const newData = [...dataSource]; | ||
const index = newData.findIndex((item) => row.uid === item.uid); | ||
const item = newData[index]; | ||
newData.splice(index, 1, { | ||
CH3CHO marked this conversation as resolved.
Show resolved
Hide resolved
|
||
...item, | ||
...row, | ||
}); | ||
setDataSource(newData); | ||
onChange(newData); | ||
}; | ||
|
||
const components = { | ||
body: { | ||
row: EditableRow, | ||
cell: EditableCell, | ||
}, | ||
}; | ||
|
||
const columns = defaultColumns.map((col) => { | ||
if (!col.editable) { | ||
return col; | ||
} | ||
return { | ||
...col, | ||
onCell: (record: DataType) => ({ | ||
record, | ||
editable: col.editable, | ||
dataIndex: col.dataIndex, | ||
title: col.title, | ||
required: col.required, | ||
nodeType: col.dataIndex === 'matchType' ? 'select' : 'input', | ||
handleSave, | ||
}), | ||
}; | ||
}); | ||
|
||
return ( | ||
<div> | ||
<Table | ||
components={components} | ||
size="small" | ||
className={styles.factor} | ||
dataSource={dataSource} | ||
columns={columns as ColumnTypes} | ||
pagination={false} | ||
rowKey={(record) => record.uid} | ||
/> | ||
<Button onClick={handleAdd} type="link"> | ||
<PlusOutlined /> | ||
</Button> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ArrayForm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个 :global 的意图是啥?