You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by zh...@apache.org on 2022/01/31 04:24:30 UTC

[dolphinscheduler] branch dev updated: [Feature][UI Next] Add custom parameters to form (#8271)

This is an automated email from the ASF dual-hosted git repository.

zhongjiajie pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 6be2201  [Feature][UI Next] Add custom parameters to form (#8271)
6be2201 is described below

commit 6be220129fe214eeb56b9e774ef42c65b78bffa8
Author: Amy0104 <97...@users.noreply.github.com>
AuthorDate: Mon Jan 31 12:24:16 2022 +0800

    [Feature][UI Next] Add custom parameters to form (#8271)
---
 .../components/form/fields/custom-parameters.ts    | 86 ++++++++++++++++++++++
 .../src/components/form/fields/get-field.ts        | 61 +++++++++++++++
 .../form/{use-form.ts => fields/index.ts}          | 32 +-------
 .../form/{use-form.ts => fields/input.ts}          | 34 +++------
 .../form/{use-form.ts => fields/monaco-editor.ts}  | 34 +++------
 .../components/form/{fields.ts => fields/radio.ts} | 31 +-------
 .../src/components/form/get-elements-by-json.ts    | 35 ++-------
 .../src/components/form/types.ts                   |  5 +-
 .../src/components/form/use-form.ts                |  4 +-
 9 files changed, 187 insertions(+), 135 deletions(-)

diff --git a/dolphinscheduler-ui-next/src/components/form/fields/custom-parameters.ts b/dolphinscheduler-ui-next/src/components/form/fields/custom-parameters.ts
new file mode 100644
index 0000000..a224fd2
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/form/fields/custom-parameters.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 { h } from 'vue'
+import { NFormItem, NSpace, NButton, NIcon } from 'naive-ui'
+import { PlusCircleOutlined, DeleteOutlined } from '@vicons/antd'
+import getField from './get-field'
+import { formatValidate } from '../utils'
+import type { IFieldParams, IJsonItem, FormItemRule } from '../types'
+
+interface ICustomParameters extends Omit<IFieldParams, 'rules'> {
+  rules?: { [key: string]: FormItemRule }[]
+}
+
+export function renderCustomParameters(params: ICustomParameters) {
+  const { fields, field, children = [], rules = [] } = params
+  let defaultValue: { [field: string]: any } = {}
+  let ruleItem: { [key: string]: FormItemRule } = {}
+  children.forEach((child) => {
+    defaultValue[child.field] = child.value || null
+    if (child.validate) ruleItem[child.field] = formatValidate(child.validate)
+  })
+  const getChild = (item: object, i: number) =>
+    children.map((child: IJsonItem) => {
+      return h(
+        NFormItem,
+        {
+          showLabel: false,
+          path: `${field}[${i}].${child.field}`
+        },
+        () => getField(child, item)
+      )
+    })
+
+  const getChildren = () =>
+    fields[field].map((item: object, i: number) => {
+      return h(NSpace, { ':key': i }, () => [
+        ...getChild(item, i),
+        h(
+          NButton,
+          {
+            tertiary: true,
+            circle: true,
+            type: 'error',
+            onClick: () => {
+              fields[field].splice(i, 1)
+              rules.splice(i, 1)
+            }
+          },
+          () => h(NIcon, { size: 24 }, () => h(DeleteOutlined))
+        )
+      ])
+    })
+
+  return h(NSpace, null, () => [
+    ...getChildren(),
+    h(
+      NButton,
+      {
+        tertiary: true,
+        circle: true,
+        type: 'info',
+        onClick: () => {
+          rules.push(ruleItem)
+          fields[field].push({ ...defaultValue })
+          console.log(rules)
+        }
+      },
+      () => h(NIcon, { size: 24 }, () => h(PlusCircleOutlined))
+    )
+  ])
+}
diff --git a/dolphinscheduler-ui-next/src/components/form/fields/get-field.ts b/dolphinscheduler-ui-next/src/components/form/fields/get-field.ts
new file mode 100644
index 0000000..f0fe779
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/form/fields/get-field.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 * as Field from './index'
+import type { FormRules } from 'naive-ui'
+import type { IJsonItem } from '../types'
+
+const getField = (
+  item: IJsonItem,
+  fields: { [field: string]: any },
+  rules?: FormRules
+) => {
+  const { type, props = {}, field, options, children } = item
+  // TODO Support other widgets later
+  if (type === 'radio') {
+    return Field.renderRadio({
+      field,
+      fields,
+      props,
+      options
+    })
+  }
+  if (type === 'editor') {
+    return Field.renderEditor({
+      field,
+      fields,
+      props
+    })
+  }
+
+  if (type === 'custom-parameters') {
+    const params = {
+      field,
+      fields,
+      children,
+      props,
+      rules: []
+    }
+    if (rules) {
+      params.rules = rules[field] = []
+    }
+    return Field.renderCustomParameters(params)
+  }
+
+  return Field.renderInput({ field, fields, props })
+}
+
+export default getField
diff --git a/dolphinscheduler-ui-next/src/components/form/use-form.ts b/dolphinscheduler-ui-next/src/components/form/fields/index.ts
similarity index 60%
copy from dolphinscheduler-ui-next/src/components/form/use-form.ts
copy to dolphinscheduler-ui-next/src/components/form/fields/index.ts
index a5e5e8c..5c01ec8 100644
--- a/dolphinscheduler-ui-next/src/components/form/use-form.ts
+++ b/dolphinscheduler-ui-next/src/components/form/fields/index.ts
@@ -15,31 +15,7 @@
  * limitations under the License.
  */
 
-import { reactive, ref } from 'vue'
-
-export function useForm() {
-  const state = reactive({
-    formRef: ref()
-  })
-
-  const validate = () => {
-    state.formRef.validate()
-  }
-
-  const setValues = (initialValues: { [field: string]: any }) => {
-    for (let [key, value] of Object.entries(initialValues)) {
-      state.formRef.model[key] = value
-    }
-  }
-
-  const restoreValidation = () => {
-    state.formRef.restoreValidation()
-  }
-
-  return {
-    state,
-    validate,
-    setValues,
-    restoreValidation
-  }
-}
+export { renderInput } from './input'
+export { renderRadio } from './radio'
+export { renderEditor } from './monaco-editor'
+export { renderCustomParameters } from './custom-parameters'
diff --git a/dolphinscheduler-ui-next/src/components/form/use-form.ts b/dolphinscheduler-ui-next/src/components/form/fields/input.ts
similarity index 61%
copy from dolphinscheduler-ui-next/src/components/form/use-form.ts
copy to dolphinscheduler-ui-next/src/components/form/fields/input.ts
index a5e5e8c..50f38c0 100644
--- a/dolphinscheduler-ui-next/src/components/form/use-form.ts
+++ b/dolphinscheduler-ui-next/src/components/form/fields/input.ts
@@ -15,31 +15,15 @@
  * limitations under the License.
  */
 
-import { reactive, ref } from 'vue'
+import { h } from 'vue'
+import { NInput } from 'naive-ui'
+import type { IFieldParams } from '../types'
 
-export function useForm() {
-  const state = reactive({
-    formRef: ref()
+export function renderInput(params: IFieldParams) {
+  const { props, fields, field } = params
+  return h(NInput, {
+    ...props,
+    value: fields[field],
+    onUpdateValue: (value: string) => void (fields[field] = value)
   })
-
-  const validate = () => {
-    state.formRef.validate()
-  }
-
-  const setValues = (initialValues: { [field: string]: any }) => {
-    for (let [key, value] of Object.entries(initialValues)) {
-      state.formRef.model[key] = value
-    }
-  }
-
-  const restoreValidation = () => {
-    state.formRef.restoreValidation()
-  }
-
-  return {
-    state,
-    validate,
-    setValues,
-    restoreValidation
-  }
 }
diff --git a/dolphinscheduler-ui-next/src/components/form/use-form.ts b/dolphinscheduler-ui-next/src/components/form/fields/monaco-editor.ts
similarity index 61%
copy from dolphinscheduler-ui-next/src/components/form/use-form.ts
copy to dolphinscheduler-ui-next/src/components/form/fields/monaco-editor.ts
index a5e5e8c..d51f5f0 100644
--- a/dolphinscheduler-ui-next/src/components/form/use-form.ts
+++ b/dolphinscheduler-ui-next/src/components/form/fields/monaco-editor.ts
@@ -15,31 +15,15 @@
  * limitations under the License.
  */
 
-import { reactive, ref } from 'vue'
+import { h } from 'vue'
+import Editor from '@/components/monaco-editor'
+import type { IFieldParams } from '../types'
 
-export function useForm() {
-  const state = reactive({
-    formRef: ref()
+export function renderEditor(params: IFieldParams) {
+  const { props, fields, field } = params
+  return h(Editor, {
+    ...props,
+    value: fields[field],
+    onUpdateValue: (value: string) => void (fields[field] = value)
   })
-
-  const validate = () => {
-    state.formRef.validate()
-  }
-
-  const setValues = (initialValues: { [field: string]: any }) => {
-    for (let [key, value] of Object.entries(initialValues)) {
-      state.formRef.model[key] = value
-    }
-  }
-
-  const restoreValidation = () => {
-    state.formRef.restoreValidation()
-  }
-
-  return {
-    state,
-    validate,
-    setValues,
-    restoreValidation
-  }
 }
diff --git a/dolphinscheduler-ui-next/src/components/form/fields.ts b/dolphinscheduler-ui-next/src/components/form/fields/radio.ts
similarity index 60%
rename from dolphinscheduler-ui-next/src/components/form/fields.ts
rename to dolphinscheduler-ui-next/src/components/form/fields/radio.ts
index e1d5b85..821bb89 100644
--- a/dolphinscheduler-ui-next/src/components/form/fields.ts
+++ b/dolphinscheduler-ui-next/src/components/form/fields/radio.ts
@@ -16,29 +16,16 @@
  */
 
 import { h } from 'vue'
-import { NInput, NRadio, NRadioGroup, NSpace } from 'naive-ui'
-import Editor from '@/components/monaco-editor'
-import type { IFieldParams } from './types'
+import { NRadio, NRadioGroup, NSpace } from 'naive-ui'
+import type { IFieldParams, IOption } from '../types'
 
-// TODO Support other widgets later
-// Input
-export function renderInput(params: IFieldParams) {
-  const { props, fields, field } = params
-  return h(NInput, {
-    ...props,
-    value: fields[field],
-    onUpdateValue: (value) => void (fields[field] = value)
-  })
-}
-
-// Radio && RadioGroup
 export function renderRadio(params: IFieldParams) {
   const { props, fields, field, options } = params
   if (!options || options.length === 0) {
     return h(NRadio, {
       ...props,
       value: fields[field],
-      onUpdateChecked: (checked) => void (fields[field] = checked)
+      onUpdateChecked: (checked: boolean) => void (fields[field] = checked)
     })
   }
   return h(
@@ -49,17 +36,7 @@ export function renderRadio(params: IFieldParams) {
     },
     () =>
       h(NSpace, null, () =>
-        options.map((option) => h(NRadio, option, () => option.label))
+        options.map((option: IOption) => h(NRadio, option, () => option.label))
       )
   )
 }
-
-// Editor
-export function renderEditor(params: IFieldParams) {
-  const { props, fields, field } = params
-  return h(Editor, {
-    ...props,
-    value: fields[field],
-    onUpdateValue: (value) => void (fields[field] = value)
-  })
-}
diff --git a/dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts b/dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts
index 48fdef3..a5911c4 100644
--- a/dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts
+++ b/dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts
@@ -15,8 +15,8 @@
  * limitations under the License.
  */
 
-import * as Field from './fields'
 import { formatValidate } from './utils'
+import getField from './fields/get-field'
 import type { FormRules } from 'naive-ui'
 import type { IJsonItem } from './types'
 
@@ -28,36 +28,17 @@ export default function getElementByJson(
   const initialValues: { [field: string]: any } = {}
   const elements = []
 
-  const getElement = (item: IJsonItem) => {
-    const { type, props = {}, field, options } = item
-    // TODO Support other widgets later
-    if (type === 'radio') {
-      return Field.renderRadio({
-        field,
-        fields,
-        props,
-        options
-      })
-    }
-    if (type === 'editor') {
-      return Field.renderEditor({
-        field,
-        fields,
-        props
-      })
-    }
-
-    return Field.renderInput({ field, fields, props })
-  }
-
   for (let item of json) {
-    fields[item.field] = item.value
-    initialValues[item.field] = item.value
+    if (item.value) {
+      fields[item.field] = item.value
+      initialValues[item.field] = item.value
+    }
     if (item.validate) rules[item.field] = formatValidate(item.validate)
     elements.push({
       label: item.name,
-      path: item.field,
-      widget: () => getElement(item)
+      path: !item.children ? item.field : '',
+      showLabel: !!item.name,
+      widget: () => getField(item, fields, rules)
     })
   }
 
diff --git a/dolphinscheduler-ui-next/src/components/form/types.ts b/dolphinscheduler-ui-next/src/components/form/types.ts
index 70993cd..de20743 100644
--- a/dolphinscheduler-ui-next/src/components/form/types.ts
+++ b/dolphinscheduler-ui-next/src/components/form/types.ts
@@ -24,7 +24,7 @@ import type {
   SelectOption
 } from 'naive-ui'
 
-type IType = 'input' | 'radio' | 'editor'
+type IType = 'input' | 'radio' | 'editor' | 'custom-parameters'
 
 type IOption = SelectOption
 
@@ -42,6 +42,8 @@ interface IFieldParams {
   props: object
   fields: { [field: string]: any }
   options?: IOption[]
+  rules?: FormRules | { [key: string]: FormRules }
+  children?: IJsonItem[]
 }
 
 interface IJsonItem {
@@ -53,6 +55,7 @@ interface IJsonItem {
   validate?: FormItemRule
   value?: any
   options?: IOption[]
+  children?: IJsonItem[]
 }
 
 export {
diff --git a/dolphinscheduler-ui-next/src/components/form/use-form.ts b/dolphinscheduler-ui-next/src/components/form/use-form.ts
index a5e5e8c..8c25ca9 100644
--- a/dolphinscheduler-ui-next/src/components/form/use-form.ts
+++ b/dolphinscheduler-ui-next/src/components/form/use-form.ts
@@ -22,8 +22,8 @@ export function useForm() {
     formRef: ref()
   })
 
-  const validate = () => {
-    state.formRef.validate()
+  const validate = (...args: []) => {
+    state.formRef.validate(...args)
   }
 
   const setValues = (initialValues: { [field: string]: any }) => {