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/paimon-webui.git

commit 4e0f9bf61f5a3cb6c5950b09d93417e8dce179db
Author: s7monk <34889415+s7m...@users.noreply.github.com>
AuthorDate: Wed Jul 10 11:34:25 2024 +0800

    [Improvement] Support indeterminate keys for permission configuration of 
role creation (#489)
---
 paimon-web-ui/src/api/models/role/types.ts         |  1 +
 .../system/role/components/role-form/index.tsx     | 11 +++-
 paimon-web-ui/src/views/system/role/index.tsx      | 59 ++++++++++++++++++++--
 3 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/paimon-web-ui/src/api/models/role/types.ts 
b/paimon-web-ui/src/api/models/role/types.ts
index 828ef7b9..693196fe 100644
--- a/paimon-web-ui/src/api/models/role/types.ts
+++ b/paimon-web-ui/src/api/models/role/types.ts
@@ -55,4 +55,5 @@ export interface RoleDTO {
   enabled: boolean
   remark?: string
   menuIds: number[]
+  indeterminateKeys?: number[]
 }
diff --git a/paimon-web-ui/src/views/system/role/components/role-form/index.tsx 
b/paimon-web-ui/src/views/system/role/components/role-form/index.tsx
index 41eab85e..95a93e65 100644
--- a/paimon-web-ui/src/views/system/role/components/role-form/index.tsx
+++ b/paimon-web-ui/src/views/system/role/components/role-form/index.tsx
@@ -41,6 +41,7 @@ const props = {
       enabled: true,
       remark: '',
       menuIds: [],
+      indeterminateKeys: [],
     }),
   },
   'onUpdate:formValue': [Function, Object] as PropType<((value: RoleDTO) => 
void) | undefined>,
@@ -95,6 +96,10 @@ export default defineComponent({
       props.formValue.menuIds = checkIds
     }
 
+    const onUpdateIndeterminateKeys = (indeterminateKeys: Array<number>) => {
+      props.formValue.indeterminateKeys = indeterminateKeys
+    }
+
     const handleConfirm = async () => {
       await formRef.value.validate()
       props && props.onConfirm && props.onConfirm()
@@ -109,6 +114,7 @@ export default defineComponent({
         enabled: true,
         remark: '',
         menuIds: [],
+        indeterminateKeys: [],
       })
     }
 
@@ -120,6 +126,7 @@ export default defineComponent({
       handleCloseModal,
       renderLabel,
       onUpdateMenuIds,
+      onUpdateIndeterminateKeys,
       handleConfirm,
       t,
     }
@@ -160,11 +167,13 @@ export default defineComponent({
                 <n-form-item label={this.t('system.role.permission_setting')} 
path="menuIds">
                   <n-tree
                     key-field="id"
-                    default-expand-all
+                    cascade
                     block-line
                     renderLabel={this.renderLabel}
                     onUpdate:checkedKeys={this.onUpdateMenuIds}
+                    onUpdate:indeterminateKeys={this.onUpdateIndeterminateKeys}
                     checkedKeys={this.formValue.menuIds}
+                    indeterminateKeys={this.formValue.indeterminateKeys}
                     data={this.permissionTree}
                     expand-on-click
                     checkable
diff --git a/paimon-web-ui/src/views/system/role/index.tsx 
b/paimon-web-ui/src/views/system/role/index.tsx
index b502d519..d3d1f30e 100644
--- a/paimon-web-ui/src/views/system/role/index.tsx
+++ b/paimon-web-ui/src/views/system/role/index.tsx
@@ -17,13 +17,14 @@ under the License. */
 
 import dayjs from 'dayjs'
 import { EditOutlined } from '@vicons/antd'
+import { Add } from '@vicons/ionicons5'
 import styles from './index.module.scss'
 import { useTable } from './use-table'
 import RoleForm from './components/role-form'
 import RoleDetail from './components/role-detail'
 import RoleDelete from './components/role-delete'
 import { createRole, getPermissionByRoleId, updateRole } from 
'@/api/models/role'
-import type { Role, RoleDTO } from '@/api/models/role/types'
+import type { Role, RoleDTO, RoleMenu } from '@/api/models/role/types'
 
 export default defineComponent({
   name: 'RolePage',
@@ -109,17 +110,64 @@ export default defineComponent({
       enabled: true,
       remark: '',
       menuIds: [],
+      indeterminateKeys: [],
     })
 
+    function inferIndeterminateKeys(checkedKeys: number[], allNodes: 
RoleMenu[]): { updatedCheckedKeys: number[], indeterminateKeys: number[] } {
+      const indeterminateKeys = new Set<number>()
+      const updatedCheckedKeys = new Set<number>(checkedKeys)
+
+      function checkNode(node: RoleMenu): boolean {
+        let childCheckedCount = 0
+        const childCount = node.children ? node.children.length : 0
+
+        if (childCount > 0) {
+          let allChildrenChecked = true
+
+          node.children.forEach((child) => {
+            const childIsChecked = checkNode(child)
+            if (childIsChecked) {
+              childCheckedCount++
+            }
+            else {
+              allChildrenChecked = false
+            }
+          })
+
+          if (childCheckedCount > 0 && childCheckedCount < childCount) {
+            indeterminateKeys.add(node.id)
+            updatedCheckedKeys.delete(node.id)
+          }
+
+          return allChildrenChecked
+        }
+
+        return checkedKeys.includes(node.id)
+      }
+
+      allNodes.forEach((node) => {
+        if (checkNode(node) && !checkedKeys.includes(node.id)) {
+          indeterminateKeys.add(node.id)
+        }
+      })
+
+      return {
+        updatedCheckedKeys: Array.from(updatedCheckedKeys),
+        indeterminateKeys: Array.from(indeterminateKeys),
+      }
+    }
+
     async function getDetail(role: Role) {
       const res = await getPermissionByRoleId(role.id)
+      const { updatedCheckedKeys, indeterminateKeys } = 
inferIndeterminateKeys(res?.data?.checkedKeys, res?.data?.menus)
       formValue.value = {
         id: role.id,
         roleName: role.roleName,
         roleKey: role.roleKey,
         enabled: role.enabled,
         remark: role.remark,
-        menuIds: res?.data?.checkedKeys,
+        menuIds: updatedCheckedKeys,
+        indeterminateKeys,
       }
     }
 
@@ -175,7 +223,12 @@ export default defineComponent({
           <n-space vertical>
             <n-space justify="space-between">
               <n-space>
-                <n-button onClick={this.handleCreateModal} 
type="primary">{this.t('system.user.add')}</n-button>
+                <n-button onClick={this.handleCreateModal} type="primary">
+                  {{
+                    icon: () => <n-icon component={Add} />,
+                    default: () => this.t('system.role.create'),
+                  }}
+                </n-button>
               </n-space>
               <n-space>
                 <></>

Reply via email to