This is an automated email from the ASF dual-hosted git repository.
nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-paimon-webui.git
The following commit(s) were added to refs/heads/main by this push:
new 3738f70 [Feature] Introduce dynamic form (#84)
3738f70 is described below
commit 3738f708bcd772e849a3964241d3d508e6def1ff
Author: labbomb <[email protected]>
AuthorDate: Sat Oct 28 16:21:42 2023 +0800
[Feature] Introduce dynamic form (#84)
---
paimon-web-ui-new/package.json | 2 +
paimon-web-ui-new/pnpm-lock.yaml | 15 ++-
.../dynamic-form/fields/checkbox.ts} | 34 ++++--
.../components/dynamic-form/fields/get-field.ts | 41 +++++++
.../dynamic-form/fields/index.ts} | 13 +--
.../dynamic-form/fields/input.ts} | 18 +--
.../src/components/dynamic-form/fields/radio.ts | 45 ++++++++
.../dynamic-form/fields/select.ts} | 25 +++--
.../dynamic-form/fields/switch.ts} | 25 +++--
.../dynamic-form/get-elements-by-json.ts | 49 ++++++++
.../src/components/dynamic-form/index.tsx | 71 ++++++++++++
.../src/components/dynamic-form/types.ts | 86 ++++++++++++++
.../src/components/dynamic-form/use-form.ts | 76 +++++++++++++
paimon-web-ui-new/src/components/modal/index.tsx | 123 +++++++++++++++++++++
paimon-web-ui-new/src/components/modal/use-task.ts | 61 ++++++++++
.../cdc => }/components/table-action/index.tsx | 0
.../en/modules/layout.ts => form-lib/index.ts} | 9 +-
.../src/form-lib/source/use-cdc-list.ts | 76 +++++++++++++
paimon-web-ui-new/src/locales/en/modules/cdc.ts | 5 +
paimon-web-ui-new/src/locales/en/modules/layout.ts | 4 +-
paimon-web-ui-new/src/locales/zh/modules/cdc.ts | 5 +
paimon-web-ui-new/src/locales/zh/modules/layout.ts | 4 +-
.../src/views/cdc/components/list/index.tsx | 19 +++-
23 files changed, 754 insertions(+), 52 deletions(-)
diff --git a/paimon-web-ui-new/package.json b/paimon-web-ui-new/package.json
index 6fb7ba9..27fd659 100644
--- a/paimon-web-ui-new/package.json
+++ b/paimon-web-ui-new/package.json
@@ -13,6 +13,7 @@
},
"dependencies": {
"dart-sass": "^1.25.0",
+ "lodash": "^4.17.21",
"mitt": "^3.0.1",
"monaco-editor": "^0.43.0",
"pinia": "^2.1.6",
@@ -27,6 +28,7 @@
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
+ "@types/lodash": "^4.14.200",
"@types/node": "^18.17.15",
"@varlet/axle": "^0.1.2",
"@vicons/ionicons5": "^0.12.0",
diff --git a/paimon-web-ui-new/pnpm-lock.yaml b/paimon-web-ui-new/pnpm-lock.yaml
index eb3e50d..6252459 100644
--- a/paimon-web-ui-new/pnpm-lock.yaml
+++ b/paimon-web-ui-new/pnpm-lock.yaml
@@ -23,6 +23,9 @@ dependencies:
dart-sass:
specifier: ^1.25.0
version: 1.25.0
+ lodash:
+ specifier: ^4.17.21
+ version: 4.17.21
mitt:
specifier: ^3.0.1
version: 3.0.1
@@ -61,6 +64,9 @@ devDependencies:
'@tsconfig/node18':
specifier: ^18.2.2
version: 18.2.2
+ '@types/lodash':
+ specifier: ^4.14.200
+ version: 4.14.200
'@types/node':
specifier: ^18.17.15
version: 18.17.15
@@ -845,11 +851,11 @@ packages:
/@types/[email protected]:
resolution: {integrity:
sha512-ZTcmhiI3NNU7dEvWLZJkzG6ao49zOIjEgIE0RgV7wbPxU0f2xT3VSAHw2gmst8swH6V0YkLRGp4qPlX/6I90MQ==}
dependencies:
- '@types/lodash': 4.14.198
+ '@types/lodash': 4.14.200
dev: true
- /@types/[email protected]:
- resolution: {integrity:
sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==}
+ /@types/[email protected]:
+ resolution: {integrity:
sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==}
dev: true
/@types/[email protected]:
@@ -2709,7 +2715,6 @@ packages:
/[email protected]:
resolution: {integrity:
sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
- dev: true
/[email protected]:
resolution: {integrity:
sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@@ -2821,7 +2826,7 @@ packages:
'@css-render/plugin-bem': 0.15.12([email protected])
'@css-render/vue3-ssr': 0.15.12([email protected])
'@types/katex': 0.14.0
- '@types/lodash': 4.14.198
+ '@types/lodash': 4.14.200
'@types/lodash-es': 4.17.9
async-validator: 4.2.5
css-render: 0.15.12
diff --git a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
b/paimon-web-ui-new/src/components/dynamic-form/fields/checkbox.ts
similarity index 51%
copy from paimon-web-ui-new/src/locales/zh/modules/layout.ts
copy to paimon-web-ui-new/src/components/dynamic-form/fields/checkbox.ts
index 313b4d3..980a31f 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
+++ b/paimon-web-ui-new/src/components/dynamic-form/fields/checkbox.ts
@@ -15,11 +15,31 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
-export default {
- playground: '查询控制台',
- metadata: '元数据管理',
- cdc_ingestion: 'CDC 集成',
- system: '系统管理',
- light: '浅色',
- dark: '暗色'
+import { NCheckbox, NCheckboxGroup, NSpace } from 'naive-ui'
+import { isFunction } from 'lodash'
+import type { IJsonItem } from '../types'
+
+export function renderCheckbox(
+ item: IJsonItem,
+ fields: { [field: string]: any }
+) {
+ const { props, field, options } = isFunction(item) ? item() : item
+ if (!options) {
+ return h(NCheckbox, {
+ ...props,
+ value: fields[field],
+ onUpdateChecked: (checked: boolean) => void (fields[field] = checked)
+ })
+ }
+ return h(
+ NCheckboxGroup,
+ {
+ value: fields[field],
+ onUpdateValue: (value) => void (fields[field] = value)
+ },
+ () =>
+ h(NSpace, null, () =>
+ unref(options).map((option: object) => h(NCheckbox, { ...option }))
+ )
+ )
}
diff --git a/paimon-web-ui-new/src/components/dynamic-form/fields/get-field.ts
b/paimon-web-ui-new/src/components/dynamic-form/fields/get-field.ts
new file mode 100644
index 0000000..39bfa1e
--- /dev/null
+++ b/paimon-web-ui-new/src/components/dynamic-form/fields/get-field.ts
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as Field from './index'
+import { camelCase, upperFirst, isFunction } from 'lodash'
+import type { IFormRules, IJsonItem } from '../types'
+
+const TYPES = [
+ 'input',
+ 'radio',
+ 'switch',
+ 'select',
+ 'checkbox',
+]
+
+const getField = (
+ item: IJsonItem,
+ fields: { [field: string]: any },
+ rules?: IFormRules
+) => {
+ const { type = 'input' } = isFunction(item) ? item() : item
+ if (!TYPES.includes(type)) return null
+ const renderTypeName = `render${upperFirst(camelCase(type))}`
+ // @ts-ignore
+ return Field[renderTypeName](item, fields)
+}
+
+export default getField
diff --git a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
b/paimon-web-ui-new/src/components/dynamic-form/fields/index.ts
similarity index 79%
copy from paimon-web-ui-new/src/locales/zh/modules/layout.ts
copy to paimon-web-ui-new/src/components/dynamic-form/fields/index.ts
index 313b4d3..477b947 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
+++ b/paimon-web-ui-new/src/components/dynamic-form/fields/index.ts
@@ -15,11 +15,8 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
-export default {
- playground: '查询控制台',
- metadata: '元数据管理',
- cdc_ingestion: 'CDC 集成',
- system: '系统管理',
- light: '浅色',
- dark: '暗色'
-}
+export { renderInput } from './input'
+export { renderRadio } from './radio'
+export { renderSwitch } from './switch'
+export { renderSelect } from './select'
+export { renderCheckbox } from './checkbox'
diff --git a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
b/paimon-web-ui-new/src/components/dynamic-form/fields/input.ts
similarity index 66%
copy from paimon-web-ui-new/src/locales/zh/modules/layout.ts
copy to paimon-web-ui-new/src/components/dynamic-form/fields/input.ts
index 313b4d3..5399825 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
+++ b/paimon-web-ui-new/src/components/dynamic-form/fields/input.ts
@@ -15,11 +15,15 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
-export default {
- playground: '查询控制台',
- metadata: '元数据管理',
- cdc_ingestion: 'CDC 集成',
- system: '系统管理',
- light: '浅色',
- dark: '暗色'
+import { isFunction } from 'lodash'
+import type { IJsonItem } from '../types'
+import { NInput } from 'naive-ui'
+
+export function renderInput(item: IJsonItem, fields: { [field: string]: any })
{
+ const { props, field } = isFunction(item) ? item() : item
+ return h(NInput, {
+ ...props,
+ value: fields[field],
+ onUpdateValue: (value: string) => void (fields[field] = value)
+ })
}
diff --git a/paimon-web-ui-new/src/components/dynamic-form/fields/radio.ts
b/paimon-web-ui-new/src/components/dynamic-form/fields/radio.ts
new file mode 100644
index 0000000..65d2bba
--- /dev/null
+++ b/paimon-web-ui-new/src/components/dynamic-form/fields/radio.ts
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import { NRadio, NRadioGroup, NSpace } from 'naive-ui'
+import { isFunction } from 'lodash'
+import type { IJsonItem, IOption } from '../types'
+
+export function renderRadio(item: IJsonItem, fields: { [field: string]: any })
{
+ const { props, field, options } = isFunction(item) ? item() : item
+ if (!options) {
+ return h(NRadio, {
+ ...props,
+ value: fields[field],
+ onUpdateChecked: (checked: boolean) => void (fields[field] = checked)
+ })
+ }
+ return h(
+ NRadioGroup,
+ {
+ ...props,
+ value: fields[field],
+ onUpdateValue: (value: any) => void (fields[field] = value)
+ },
+ () =>
+ h(NSpace, null, () =>
+ unref(options).map((option: IOption) =>
+ h(NRadio, option, () => option.label)
+ )
+ )
+ )
+}
diff --git a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
b/paimon-web-ui-new/src/components/dynamic-form/fields/select.ts
similarity index 60%
copy from paimon-web-ui-new/src/locales/zh/modules/layout.ts
copy to paimon-web-ui-new/src/components/dynamic-form/fields/select.ts
index 313b4d3..fabd2db 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
+++ b/paimon-web-ui-new/src/components/dynamic-form/fields/select.ts
@@ -15,11 +15,22 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
-export default {
- playground: '查询控制台',
- metadata: '元数据管理',
- cdc_ingestion: 'CDC 集成',
- system: '系统管理',
- light: '浅色',
- dark: '暗色'
+import { NSelect } from 'naive-ui'
+import { isFunction } from 'lodash'
+import type { IJsonItem } from '../types'
+
+export function renderSelect(
+ item: IJsonItem,
+ fields: { [field: string]: any }
+) {
+ const { props, field, options = [] } = isFunction(item) ? item() : item
+ return h(NSelect, {
+ ...props,
+ value: fields[field],
+ onUpdateValue: (value: any) => {
+ void (fields[field] = value)
+ if (props?.onUpdateValue) props.onUpdateValue(value)
+ },
+ options: unref(options)
+ })
}
diff --git a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
b/paimon-web-ui-new/src/components/dynamic-form/fields/switch.ts
similarity index 63%
copy from paimon-web-ui-new/src/locales/zh/modules/layout.ts
copy to paimon-web-ui-new/src/components/dynamic-form/fields/switch.ts
index 313b4d3..5bf47dc 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
+++ b/paimon-web-ui-new/src/components/dynamic-form/fields/switch.ts
@@ -15,11 +15,22 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
-export default {
- playground: '查询控制台',
- metadata: '元数据管理',
- cdc_ingestion: 'CDC 集成',
- system: '系统管理',
- light: '浅色',
- dark: '暗色'
+import { NSwitch } from 'naive-ui'
+import { isFunction } from 'lodash'
+import type { IJsonItem } from '../types'
+
+export function renderSwitch(
+ item: IJsonItem,
+ fields: { [field: string]: any }
+) {
+ const { props, field, slots = {} } = isFunction(item) ? item() : item
+ return h(
+ NSwitch,
+ {
+ ...props,
+ value: fields[field],
+ onUpdateValue: (value: string) => void (fields[field] = value)
+ },
+ { ...slots }
+ )
}
diff --git
a/paimon-web-ui-new/src/components/dynamic-form/get-elements-by-json.ts
b/paimon-web-ui-new/src/components/dynamic-form/get-elements-by-json.ts
new file mode 100644
index 0000000..5b22c8b
--- /dev/null
+++ b/paimon-web-ui-new/src/components/dynamic-form/get-elements-by-json.ts
@@ -0,0 +1,49 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import { useFormHooks } from './use-form'
+import getField from './fields/get-field'
+import { omit, isFunction } from 'lodash'
+import type { IFormItem, IJsonItem, IFormRules } from './types'
+
+export default function getElementByJson(
+ json: IJsonItem[],
+ fields: { [field: string]: any }
+) {
+ const rules: IFormRules = {}
+ const initialValues: { [field: string]: any } = {}
+ const elements: IFormItem[] = []
+ for (const item of json) {
+ const mergedItem = isFunction(item) ? item() : item
+ const { name, value, field, children, validate, ...rest } = mergedItem
+ if (value || value === 0) {
+ fields[field] = value
+ initialValues[field] = value
+ }
+ if (validate) rules[field] = useFormHooks().formatValidate(validate)
+ const element: IFormItem = {
+ showLabel: !!name,
+ ...omit(rest, ['type', 'props', 'options']),
+ label: name,
+ path: !children ? field : '',
+ widget: () => getField(item, fields, rules),
+ span: toRef(mergedItem, 'span') as Ref<number>
+ }
+ elements.push(element)
+ }
+ return { rules, elements, initialValues }
+}
diff --git a/paimon-web-ui-new/src/components/dynamic-form/index.tsx
b/paimon-web-ui-new/src/components/dynamic-form/index.tsx
new file mode 100644
index 0000000..97064a1
--- /dev/null
+++ b/paimon-web-ui-new/src/components/dynamic-form/index.tsx
@@ -0,0 +1,71 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import type { FormRules, GridProps, IMeta } from "./types"
+import { useFormHooks } from "./use-form"
+
+const props = {
+ loading: {
+ type: Boolean as PropType<boolean>,
+ default: false
+ },
+ gridProps: {
+ type: Object as PropType<GridProps>
+ },
+ meta: {
+ type: Object as PropType<IMeta>,
+ default: {},
+ required: true
+ },
+}
+
+export default defineComponent({
+ name: 'DynamicForm',
+ props,
+ setup(props, { expose }) {
+ const { state, ...rest } = useFormHooks()
+ expose({
+ ...rest
+ })
+ return { ...toRefs(state) }
+ },
+ render(props: { meta: IMeta; gridProps?: GridProps; loading?: boolean }) {
+ const { loading, gridProps, meta } = props
+ const { elements = [], ...restFormProps } = meta
+ return (
+ <n-spin show={loading}>
+ <n-form {...restFormProps} rules={meta.rules as FormRules}
ref='formRef'>
+ <n-grid {...gridProps}>
+ {elements.map((element) => {
+ const { span = 24, path, widget, ...formItemProps } = element
+ return (
+ <n-form-item-gi
+ {...formItemProps}
+ span={unref(span) === void 0 ? 24 : unref(span)}
+ path={path}
+ key={path || String(Date.now() + Math.random())}
+ >
+ {h(widget)}
+ </n-form-item-gi>
+ )
+ })}
+ </n-grid>
+ </n-form>
+ </n-spin>
+ )
+ }
+})
diff --git a/paimon-web-ui-new/src/components/dynamic-form/types.ts
b/paimon-web-ui-new/src/components/dynamic-form/types.ts
new file mode 100644
index 0000000..6ee0c6a
--- /dev/null
+++ b/paimon-web-ui-new/src/components/dynamic-form/types.ts
@@ -0,0 +1,86 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import type { FormItemRule, FormProps, FormRules, GridProps } from "naive-ui"
+
+type ComponentType =
+ | 'input'
+ | 'radio'
+ | 'switch'
+ | 'select'
+ | 'checkbox'
+
+
+interface IOption {
+ [key: string]: any
+}
+
+interface IFormItemRule extends Omit<FormItemRule, 'required'> {
+ required?: boolean | Ref<boolean>
+}
+
+interface IJsonItemParams {
+ type: ComponentType
+ field: string
+ name?: string
+ value?: any
+ props?: any
+ options?: IOption[] | Ref<IOption[]>
+ span?: number
+ children?: IJsonItem[]
+ validate?: IFormItemRule
+ slots?: object
+}
+
+type IJsonItem = IJsonItemParams | IJsonItemFn
+
+type IJsonItemFn = (i?: number) => IJsonItemParams
+
+interface IFormItem {
+ showLabel?: boolean
+ path: string
+ label?: string
+ widget: any
+ span?: number | Ref<number>
+ class?: string
+}
+
+type IFormRules =
+ | {
+ [path: string]: IFormItemRule | IFormItemRule[]
+ }
+ | FormRules
+
+interface IMeta extends Omit<FormProps, 'model' | 'rules'> {
+ elements?: IFormItem[]
+ model: object
+ rules: IFormRules
+}
+
+export type {
+ IJsonItem,
+ IJsonItemParams,
+ IJsonItemFn,
+ IOption,
+ ComponentType,
+ IFormItem,
+ IFormRules,
+ IFormItemRule,
+ IMeta,
+ GridProps,
+ FormRules
+}
diff --git a/paimon-web-ui-new/src/components/dynamic-form/use-form.ts
b/paimon-web-ui-new/src/components/dynamic-form/use-form.ts
new file mode 100644
index 0000000..e508191
--- /dev/null
+++ b/paimon-web-ui-new/src/components/dynamic-form/use-form.ts
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import type { FormRules, IFormItemRule } from "./types"
+
+export const useFormHooks = () => {
+ const state = reactive({
+ formRef: ref()
+ })
+
+ const validate = async (...args: []) => {
+ await state.formRef.validate(...args)
+ }
+
+ const setValues = (initialValues: { [field: string]: any }) => {
+ for (const [key, value] of Object.entries(initialValues)) {
+ state.formRef.model[key] = value
+ }
+ }
+
+ const restoreValidation = () => {
+ state.formRef.restoreValidation()
+ }
+
+ const resetValues = (initialValues: { [field: string]: any }) => {
+ const modelKeys = Object.keys(state.formRef.model)
+ for (const key of modelKeys) {
+ if (!Object.keys(initialValues).includes(key)) {
+ delete state.formRef.model[key]
+ }
+ }
+ setValues(initialValues)
+ }
+
+ const getValues = () => {
+ return state.formRef.model
+ }
+
+ const formatValidate = (
+ validate?: IFormItemRule | FormRules
+ ): IFormItemRule => {
+ if (!validate) return {}
+ if (Array.isArray(validate)) {
+ validate.forEach((item: IFormItemRule) => {
+ if (!item?.message) delete item.message
+ return item
+ })
+ }
+ if (!validate.message) delete validate.message
+ return validate
+ }
+
+ return {
+ state,
+ validate,
+ setValues,
+ getValues,
+ resetValues,
+ restoreValidation,
+ formatValidate
+ }
+}
diff --git a/paimon-web-ui-new/src/components/modal/index.tsx
b/paimon-web-ui-new/src/components/modal/index.tsx
new file mode 100644
index 0000000..6aaeec4
--- /dev/null
+++ b/paimon-web-ui-new/src/components/modal/index.tsx
@@ -0,0 +1,123 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import Form from "@/components/dynamic-form"
+import { useTask } from "./use-task"
+
+const props = {
+ title: {
+ type: String as PropType<string>,
+ default: ''
+ },
+ row: {
+ type: Object as PropType<any>,
+ default: () => {}
+ },
+ showModal: {
+ type: Boolean as PropType<boolean>,
+ default: false
+ },
+ autoFocus: {
+ type: Boolean as PropType<boolean>,
+ default: false
+ },
+ closeable: {
+ type: Boolean as PropType<boolean>,
+ default: true
+ },
+ formType: {
+ type: String as PropType<string>,
+ default: ''
+ }
+}
+
+export default defineComponent({
+ name: 'ModalPage',
+ props,
+ emits: ['confirm', 'cancel'],
+ setup(props, { expose, emit }) {
+ const { t } = useLocaleHooks()
+ const formRef = ref()
+ expose({formRef})
+
+ const { elementsRef, rulesRef, model } = useTask({
+ data: props.row,
+ formType: props.formType
+ })
+
+ const handleConfirm = () => {
+ emit('confirm')
+ }
+
+ const handleCancel = () => {
+ emit('cancel')
+ }
+
+ return {
+ t,
+ handleConfirm,
+ handleCancel,
+ formRef,
+ elementsRef,
+ rulesRef,
+ model
+ }
+ },
+ render () {
+ return (
+ <n-modal
+ v-model:show={this.showModal}
+ mask-closable={false}
+ auto-focus={this.autoFocus}
+ >
+ <n-card
+ style="width: 600px"
+ title={this.title}
+ bordered={false}
+ closable={this.closeable}
+ on-close={this.handleCancel}
+ >
+ {{
+ default: () => (
+ <Form
+ ref={this.formRef}
+ meta={{
+ ...this.model,
+ rules: this.rulesRef,
+ elements: this.elementsRef,
+ }}
+ gridProps={{
+ xGap: 10
+ }}
+ />
+ ),
+ footer: () => (
+ <n-space justify='end'>
+ <n-button onClick={this.handleCancel}>
+ {this.t('layout.cancel')}
+ </n-button>
+ <n-button type='primary' onClick={this.handleConfirm}>
+ {this.t('layout.confirm')}
+ </n-button>
+ </n-space>
+ )
+ }}
+ </n-card>
+ </n-modal>
+ )
+ }
+})
diff --git a/paimon-web-ui-new/src/components/modal/use-task.ts
b/paimon-web-ui-new/src/components/modal/use-task.ts
new file mode 100644
index 0000000..4d2a415
--- /dev/null
+++ b/paimon-web-ui-new/src/components/modal/use-task.ts
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import tasks from '@/form-lib'
+import getElementByJson from '@/components/dynamic-form/get-elements-by-json'
+import type {
+ IFormItem,
+ IJsonItem,
+ FormRules
+} from '@/components/dynamic-form/types'
+
+export function useTask({
+ data,
+ formType
+}: {
+ data: any
+ formType: string
+}): {
+ elementsRef: Ref<IFormItem[]>
+ rulesRef: Ref<FormRules>
+ model: any
+} {
+ const jsonRef = ref([]) as Ref<IJsonItem[]>
+ const elementsRef = ref([]) as Ref<IFormItem[]>
+ const rulesRef = ref({})
+
+ const params = {
+ data,
+ jsonRef,
+ updateElements: () => {
+ getElements()
+ }
+ }
+
+ const task = tasks[formType as keyof typeof tasks]
+ const { model, json } = task(params)
+ jsonRef.value = json
+ const getElements = () => {
+ const { rules, elements } = getElementByJson(jsonRef.value, model)
+ elementsRef.value = elements
+ rulesRef.value = rules
+ }
+
+ getElements()
+
+ return { elementsRef, rulesRef, model }
+}
diff --git a/paimon-web-ui-new/src/views/cdc/components/table-action/index.tsx
b/paimon-web-ui-new/src/components/table-action/index.tsx
similarity index 100%
rename from paimon-web-ui-new/src/views/cdc/components/table-action/index.tsx
rename to paimon-web-ui-new/src/components/table-action/index.tsx
diff --git a/paimon-web-ui-new/src/locales/en/modules/layout.ts
b/paimon-web-ui-new/src/form-lib/index.ts
similarity index 84%
copy from paimon-web-ui-new/src/locales/en/modules/layout.ts
copy to paimon-web-ui-new/src/form-lib/index.ts
index 31d6e66..8d366d9 100644
--- a/paimon-web-ui-new/src/locales/en/modules/layout.ts
+++ b/paimon-web-ui-new/src/form-lib/index.ts
@@ -15,11 +15,8 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
+import { useCDCList } from "./source/use-cdc-list";
+
export default {
- playground: 'Playground',
- metadata: 'MetaData',
- cdc_ingestion: 'CDC Ingestion',
- system: 'System',
- light: 'Light',
- dark: 'Dark'
+ CDCLIST: useCDCList
}
diff --git a/paimon-web-ui-new/src/form-lib/source/use-cdc-list.ts
b/paimon-web-ui-new/src/form-lib/source/use-cdc-list.ts
new file mode 100644
index 0000000..6129a2c
--- /dev/null
+++ b/paimon-web-ui-new/src/form-lib/source/use-cdc-list.ts
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import type { IJsonItem } from "@/components/dynamic-form/types"
+
+export function useCDCList(item:any) {
+ const { t } = useLocaleHooks()
+
+ const model = reactive({
+ name: item.name,
+ description: item.description,
+ synchronizationType: item.synchronizationType,
+ })
+
+ const synchronizationTypeOptions = [
+ {
+ label: t('cdc.single_table_synchronization'),
+ value: 0
+ },
+ {
+ label: t('cdc.whole_database_synchronization'),
+ value: 1
+ },
+ ]
+
+ return {
+ json: [
+ {
+ type: 'input',
+ field: 'name',
+ name: t('cdc.synchronization_job_name'),
+ props: {
+ placeholder: ''
+ },
+ validate: {
+ trigger: ['input', 'blur'],
+ required: true,
+ message: 'error',
+ validator: (validator: any, value:
string) => {
+ if (!value) {
+ return new
Error('error')
+ }
+ }
+ }
+ },
+ {
+ type: 'input',
+ field: 'description',
+ name: t('cdc.task_description'),
+ props: {
+ placeholder: ''
+ }
+ },
+ {
+ type: 'radio',
+ field: 'synchronizationType',
+ name: t('cdc.synchronization_type'),
+ options: synchronizationTypeOptions
+ },
+ ] as IJsonItem[], model
+ }
+}
diff --git a/paimon-web-ui-new/src/locales/en/modules/cdc.ts
b/paimon-web-ui-new/src/locales/en/modules/cdc.ts
index a5487e9..b8d2ca3 100644
--- a/paimon-web-ui-new/src/locales/en/modules/cdc.ts
+++ b/paimon-web-ui-new/src/locales/en/modules/cdc.ts
@@ -28,4 +28,9 @@ export default {
edit: 'Edit',
run: 'Run',
delete: 'Delete',
+ synchronization_job_name: 'Synchronization Job Name',
+ edit_synchronization_job: 'Edit Synchronization Job',
+ task_description: 'Task Description',
+ single_table_synchronization: 'Single Table Synchronization',
+ whole_database_synchronization: 'Whole Database Synchronization',
}
diff --git a/paimon-web-ui-new/src/locales/en/modules/layout.ts
b/paimon-web-ui-new/src/locales/en/modules/layout.ts
index 31d6e66..d6e8f26 100644
--- a/paimon-web-ui-new/src/locales/en/modules/layout.ts
+++ b/paimon-web-ui-new/src/locales/en/modules/layout.ts
@@ -21,5 +21,7 @@ export default {
cdc_ingestion: 'CDC Ingestion',
system: 'System',
light: 'Light',
- dark: 'Dark'
+ dark: 'Dark',
+ cancel: 'Cancel',
+ confirm: 'Confirm',
}
diff --git a/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
b/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
index 6cb6a0a..f80b3d0 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
+++ b/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
@@ -28,4 +28,9 @@ export default {
edit: '编辑',
run: '运行',
delete: '删除',
+ synchronization_job_name: '同步作业名称',
+ edit_synchronization_job: '编辑同步作业',
+ task_description: '任务描述',
+ single_table_synchronization: '单表同步',
+ whole_database_synchronization: '整库同步',
}
diff --git a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
b/paimon-web-ui-new/src/locales/zh/modules/layout.ts
index 313b4d3..e7e09ae 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/layout.ts
+++ b/paimon-web-ui-new/src/locales/zh/modules/layout.ts
@@ -21,5 +21,7 @@ export default {
cdc_ingestion: 'CDC 集成',
system: '系统管理',
light: '浅色',
- dark: '暗色'
+ dark: '暗色',
+ cancel: '取消',
+ confirm: '确认',
}
diff --git a/paimon-web-ui-new/src/views/cdc/components/list/index.tsx
b/paimon-web-ui-new/src/views/cdc/components/list/index.tsx
index 0031ac4..568cd4f 100644
--- a/paimon-web-ui-new/src/views/cdc/components/list/index.tsx
+++ b/paimon-web-ui-new/src/views/cdc/components/list/index.tsx
@@ -16,7 +16,8 @@ specific language governing permissions and limitations
under the License. */
import styles from './index.module.scss';
-import TableAction from '../table-action';
+import TableAction from '../../../../components/table-action';
+import Modal from '@/components/modal';
export default defineComponent({
name: 'ListPage',
@@ -60,6 +61,10 @@ export default defineComponent({
render: (row: any) =>
h(TableAction, {
row,
+ onHandleEdit: (row) => {
+ tableVariables.showModal = true
+ tableVariables.row = row
+ },
})
}
],
@@ -69,7 +74,9 @@ export default defineComponent({
],
pagination: {
pageSize: 10
- }
+ },
+ showModal: false,
+ row: {}
})
return {
t,
@@ -83,7 +90,13 @@ export default defineComponent({
columns={this.columns}
data={this.data}
pagination={this.pagination}
- bordered="false"
+ bordered={false}
+ />
+ <Modal
+ showModal={this.showModal}
+ title={this.t('cdc.edit_synchronization_job')}
+ formType="CDCLIST"
+ onCancel={() => this.showModal = false}
/>
</div>
)