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


The following commit(s) were added to refs/heads/main by this push:
     new 5b3805b  [Feature] Support show and mock system role management (#221)
5b3805b is described below

commit 5b3805be987885f8b42f130ef9eb455829f58aa1
Author: xiaomo <[email protected]>
AuthorDate: Wed May 15 11:27:49 2024 +0800

    [Feature] Support show and mock system role management (#221)
---
 paimon-web-ui/mock/modules/system.js               | 139 +++++++++++++++++++++
 paimon-web-ui/src/api/models/catalog/index.ts      |   2 +-
 paimon-web-ui/src/api/models/role/index.ts         |  22 +++-
 paimon-web-ui/src/api/models/role/types/role.ts    |  37 +++++-
 paimon-web-ui/src/locales/en/modules/system.ts     |  22 +++-
 paimon-web-ui/src/locales/zh/modules/system.ts     |  23 +++-
 paimon-web-ui/src/views/login/use-form.ts          |  10 +-
 .../views/metadata/components/table-form/index.tsx |   5 +-
 .../system/role/components/role-detail/index.tsx   |  77 ++++++++++++
 .../system/role/components/role-form/index.tsx     |   0
 paimon-web-ui/src/views/system/role/index.tsx      |  25 +++-
 .../src/views/system/role/use-constants.ts         |  52 --------
 .../src/views/system/role/use-constants.tsx        |  72 +++++++++++
 paimon-web-ui/src/views/system/role/use-table.ts   |  70 ++++++-----
 14 files changed, 446 insertions(+), 110 deletions(-)

diff --git a/paimon-web-ui/mock/modules/system.js 
b/paimon-web-ui/mock/modules/system.js
new file mode 100644
index 0000000..49b6e9e
--- /dev/null
+++ b/paimon-web-ui/mock/modules/system.js
@@ -0,0 +1,139 @@
+/* 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. */
+
+module.exports = (mockUtil) => ({
+  '/role/list': mockUtil({
+    "total": "2",
+    "success": true,
+    "data": [
+      {
+        "id": 1,
+        "createTime": "2024-05-11T13:49:27",
+        "updateTime": null,
+        "roleName": "admin",
+        "roleKey": "admin",
+        "sort": 1,
+        "enabled": true,
+        "isDelete": false,
+        "remark": null,
+        "flag": false,
+        "menuIds": null,
+        "permissions": null
+      },
+      {
+        "id": 2,
+        "createTime": "2024-05-11T13:49:27",
+        "updateTime": null,
+        "roleName": "common",
+        "roleKey": "common",
+        "sort": 2,
+        "enabled": true,
+        "isDelete": false,
+        "remark": null,
+        "flag": false,
+        "menuIds": null,
+        "permissions": null
+      }
+    ]
+  }),
+
+  '/menu/roleMenuTreeselect/:roleId': mockUtil({
+    "code": 200,
+    "msg": "Successfully",
+    "data": {
+      "checkedKeys": [],
+      "menus": [
+        {
+          "id": 1,
+          "label": "system",
+          "children": [
+            {
+              "id": 300,
+              "label": "menu_manager",
+              "children": [
+                {
+                  "id": 3000,
+                  "label": "menu_query"
+                },
+                {
+                  "id": 3001,
+                  "label": "menu_add"
+                },
+                {
+                  "id": 3002,
+                  "label": "menu_update"
+                },
+                {
+                  "id": 3003,
+                  "label": "menu_delete"
+                }
+              ]
+            },
+            {
+              "id": 100,
+              "label": "user_manager",
+              "children": [
+                {
+                  "id": 1000,
+                  "label": "user_query"
+                },
+                {
+                  "id": 1001,
+                  "label": "user_add"
+                },
+                {
+                  "id": 1002,
+                  "label": "user_update"
+                },
+                {
+                  "id": 1003,
+                  "label": "user_delete"
+                },
+                {
+                  "id": 1004,
+                  "label": "user_reset"
+                }
+              ]
+            },
+            {
+              "id": 200,
+              "label": "role_manager",
+              "children": [
+                {
+                  "id": 2000,
+                  "label": "role_query"
+                },
+                {
+                  "id": 2001,
+                  "label": "role_add"
+                },
+                {
+                  "id": 2002,
+                  "label": "role_update"
+                },
+                {
+                  "id": 2003,
+                  "label": "role_delete"
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  })
+})
diff --git a/paimon-web-ui/src/api/models/catalog/index.ts 
b/paimon-web-ui/src/api/models/catalog/index.ts
index a9856a8..f3f84dd 100644
--- a/paimon-web-ui/src/api/models/catalog/index.ts
+++ b/paimon-web-ui/src/api/models/catalog/index.ts
@@ -148,7 +148,7 @@ export const createColumns = () => {
  */
 export const deleteColumns = (query: ColumnParams) => {
   const { catalogName, databaseName, name, columnName } = query
-  
+
   return httpRequest.delete!<unknown, 
unknown>(`/table/column/drop/${catalogName}/${databaseName}/${name}/${columnName}`)
 }
 
diff --git a/paimon-web-ui/src/api/models/role/index.ts 
b/paimon-web-ui/src/api/models/role/index.ts
index ffc0b3f..758c186 100644
--- a/paimon-web-ui/src/api/models/role/index.ts
+++ b/paimon-web-ui/src/api/models/role/index.ts
@@ -17,13 +17,31 @@ under the License. */
 
 import httpRequest from '../../request'
 import type { ResponseOptions } from '@/api/types'
-import type { Role } from './types/role'
+import type { Role, RoleDetail, RoleParams } from './types/role'
+
+/**
+ * # permission tree
+ */
+export const getPermissionTree = () => {
+  return httpRequest.createHooks!<ResponseOptions<Role[]>>({
+    url: '/menu/treeselect',
+    method: 'get',
+  })
+}
+
+
+/**
+ * # permission tree by role Id
+ */
+export const getPermissionByRoleId = (roleId: number) => {
+  return httpRequest.get!<string, 
ResponseOptions<RoleDetail>>(`/menu/roleMenuTreeselect/${roleId}`)
+}
 
 /**
  * # List roles
  */
 export const listRoles = () => {
-  return httpRequest.createHooks!<ResponseOptions<Role[]>, any[]>({
+  return httpRequest.createHooks!<ResponseOptions<Role[]>, RoleParams>({
     url: '/role/list',
     method: 'get',
   })
diff --git a/paimon-web-ui/src/api/models/role/types/role.ts 
b/paimon-web-ui/src/api/models/role/types/role.ts
index 79bde09..386e970 100644
--- a/paimon-web-ui/src/api/models/role/types/role.ts
+++ b/paimon-web-ui/src/api/models/role/types/role.ts
@@ -15,11 +15,40 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License. */
 
+export interface RoleDetail {
+  checkedKeys: number[];
+  menus: RoleMenu[];
+}
+
+export interface RoleMenu {
+  id: number;
+  label: string;
+  children: RoleMenuChild[];
+}
+
+export interface RoleMenuChild {
+  id: number;
+  label: string;
+  children: Omit<RoleMenuChild, 'children'>[];
+}
+
 export interface Role {
+  id: number;
+  createTime: string;
+  updateTime?: string;
   roleName: string;
-  roleKey?: string;
-  sort?: number;
+  roleKey: string;
+  sort: number;
   enabled: boolean;
-  remark?: string;
-  menuIds?: number[]
+  isDelete: boolean;
+  remark: null;
+  flag: boolean;
+  menuIds: null;
+  permissions: null;
+}
+
+export interface RoleParams {
+  roleName?: string,
+  currentPage: number,
+  pageSize: number
 }
diff --git a/paimon-web-ui/src/locales/en/modules/system.ts 
b/paimon-web-ui/src/locales/en/modules/system.ts
index c1c5c31..7d8ea8f 100644
--- a/paimon-web-ui/src/locales/en/modules/system.ts
+++ b/paimon-web-ui/src/locales/en/modules/system.ts
@@ -29,4 +29,24 @@ const role = {
   enabled: 'Enabled'
 }
 
-export default { user, role }
+const roleKey = {
+  system: 'System',
+  menu_manager: 'Menu Manager',
+  user_manager: 'User Manager',
+  role_manager: 'Role Manager',
+  menu_query: 'Menu Query',
+  menu_add: 'Menu Add',
+  menu_update: 'Menu Update',
+  menu_delete: 'Menu Delete',
+  user_query: 'User Query',
+  user_add: 'User Add',
+  user_update: 'User Update',
+  user_delete: 'User Delete',
+  user_reset: 'User Reset',
+  role_query: 'Role Query',
+  role_add: 'Role Add',
+  role_update: 'Role Update',
+  role_delete: 'Role Delete'
+}
+
+export default { user, role, roleKey }
diff --git a/paimon-web-ui/src/locales/zh/modules/system.ts 
b/paimon-web-ui/src/locales/zh/modules/system.ts
index 578d752..6f91956 100644
--- a/paimon-web-ui/src/locales/zh/modules/system.ts
+++ b/paimon-web-ui/src/locales/zh/modules/system.ts
@@ -28,4 +28,25 @@ const role = {
   role_key: '角色编码',
   enabled: '是否启用'
 }
-export default { user, role }
+
+const roleKey = {
+  system: '系统管理',
+  menu_manager: '菜单管理',
+  user_manager: '用户管理',
+  role_manager: '角色管理',
+  menu_query: '菜单查询',
+  menu_add: '菜单新增',
+  menu_update: '菜单修改',
+  menu_delete: '菜单删除',
+  user_query: '用户查询',
+  user_add: '用户新增',
+  user_update: '用户修改',
+  user_delete: '用户删除',
+  user_reset: '用户重置密码',
+  role_query: '角色查询',
+  role_add: '角色新增',
+  role_update: '角色修改',
+  role_delete: '角色删除'
+}
+
+export default { user, role, roleKey }
diff --git a/paimon-web-ui/src/views/login/use-form.ts 
b/paimon-web-ui/src/views/login/use-form.ts
index daf822c..df6ad88 100644
--- a/paimon-web-ui/src/views/login/use-form.ts
+++ b/paimon-web-ui/src/views/login/use-form.ts
@@ -34,12 +34,10 @@ export function useForm() {
     state.loginForm.validate(async (errors: Array<FormValidationError>) => {
       if (!errors) {
         onLogin({
-          params: {
-            username: state.model.username,
-            password: state.model.password,
-            ldapLogin: false,
-            rememberMe: true
-          }
+          username: state.model.username,
+          password: state.model.password,
+          ldapLogin: false,
+          rememberMe: true
         })
         router.push({ path: '/' })
       }
diff --git a/paimon-web-ui/src/views/metadata/components/table-form/index.tsx 
b/paimon-web-ui/src/views/metadata/components/table-form/index.tsx
index a8fef4f..32932b4 100644
--- a/paimon-web-ui/src/views/metadata/components/table-form/index.tsx
+++ b/paimon-web-ui/src/views/metadata/components/table-form/index.tsx
@@ -176,10 +176,7 @@ export default defineComponent({
                     </n-button>
                   </n-space>
                   <ColumnFormContent
-                    onUpdateColumns={(value) => {
-                      this.formValue.tableColumns = value
-                    }}
-                    data={this.formValue.tableColumns}
+                    v-model:data={this.formValue.tableColumns}
                   />
                   <div 
class={styles.form_title}>{this.t('metadata.partition_columns')}</div>
                   <n-form-item showLabel={false} path="type">
diff --git 
a/paimon-web-ui/src/views/system/role/components/role-detail/index.tsx 
b/paimon-web-ui/src/views/system/role/components/role-detail/index.tsx
new file mode 100644
index 0000000..c927c03
--- /dev/null
+++ b/paimon-web-ui/src/views/system/role/components/role-detail/index.tsx
@@ -0,0 +1,77 @@
+/* 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 { getPermissionByRoleId } from "@/api/models/role"
+import type { Role, RoleMenu } from "@/api/models/role/types/role"
+
+export default defineComponent({
+  name: 'RoleDetail',
+  props: {
+    roleRecord: {
+      type: Object as PropType<Role>,
+      default: () => ({}),
+      require: true
+    }
+  },
+  setup(props) {
+    const { t } = useLocaleHooks()
+
+    const rolePermissionDetail = ref<RoleMenu[]>([])
+    const loading = ref(false)
+    onMounted(initDetail)
+
+    async function initDetail() {
+      loading.value = true
+      const res = await getPermissionByRoleId(props.roleRecord.id)
+      rolePermissionDetail.value = res?.data?.menus
+      loading.value = false
+    }
+
+    return {
+      loading,
+      rolePermissionDetail,
+      t,
+    }
+  },
+  render() {
+    return <n-spin show={this.loading}>
+      <n-list hoverable clickable>
+        {
+          this.rolePermissionDetail?.map((item) => (
+            <n-list-item key={item.id}>
+              <n-thing title={this.t(`system.roleKey.${item.label}`)} 
content-style="margin-top: 10px;">
+                {
+                  item.children?.map((child) => (
+                    <n-thing 
description={this.t(`system.roleKey.${child.label}`)} style="margin-top: 20px;">
+                      <n-space>
+                        {
+                          child.children?.map((buttonPermission) => (
+                            <n-tag key={child.id} 
type="info">{this.t(`system.roleKey.${buttonPermission.label}`)}</n-tag>
+                          ))
+                        }
+                      </n-space>
+                    </n-thing>
+                  ))
+                }
+              </n-thing>
+            </n-list-item>
+          ))
+        }
+      </n-list>
+    </n-spin>
+  }
+})
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
new file mode 100644
index 0000000..e69de29
diff --git a/paimon-web-ui/src/views/system/role/index.tsx 
b/paimon-web-ui/src/views/system/role/index.tsx
index b8e504a..0b5ae86 100644
--- a/paimon-web-ui/src/views/system/role/index.tsx
+++ b/paimon-web-ui/src/views/system/role/index.tsx
@@ -15,6 +15,7 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License. */
 
+import type { Role } from '@/api/models/role/types/role';
 import styles from './index.module.scss';
 import { useConstants } from './use-constants';
 import { useTable } from './use-table';
@@ -23,10 +24,21 @@ export default defineComponent({
   name: 'RolePage',
   setup() {
     const { t } = useLocaleHooks()
-    const { tableVariables, getTableData, roleList,loading} = useTable()
+    const { tableVariables, getTableData, roleList, loading } = useTable()
     const { columns } = useConstants()
-    getTableData()
-    return { ...toRefs(tableVariables), getTableData, t, columns, 
roleList,loading }
+
+    onMounted(getTableData)
+
+    const rowKey = (rowData: Role) => rowData.id
+
+    return {
+      ...toRefs(tableVariables),
+      t,
+      columns: toRef([...columns]),
+      roleList,
+      loading,
+      rowKey,
+    }
   },
   render() {
     return (
@@ -43,10 +55,11 @@ export default defineComponent({
             </n-space>
             <n-data-table
               columns={this.columns}
-              data={this.roleList?.data || []}
-              remote
-              loading={this.loading}
+              data={this.roleList || []}
               pagination={this.pagination}
+              loading={this.loading}
+              remote
+              rowKey={this.rowKey}
             />
           </n-space>
         </n-card>
diff --git a/paimon-web-ui/src/views/system/role/use-constants.ts 
b/paimon-web-ui/src/views/system/role/use-constants.ts
deleted file mode 100644
index ffb250f..0000000
--- a/paimon-web-ui/src/views/system/role/use-constants.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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. */
-
-export const useConstants = () => {
-    const { t } = useLocaleHooks()
-    const columns = [
-        {
-            title: t('system.role.role_name'),
-            key: 'roleName',
-            resizable: true
-        },
-        {
-            title: t('system.role.role_key'),
-            key: 'roleKey',
-            resizable: true
-        },
-        {
-            title: t('system.role.enabled'),
-            key: 'enabled',
-            resizable: true,
-            render: (row: any) => {
-                return row.enabled ? t('common.yes') : t('common.no')
-            }
-        },
-        {
-            title: t('common.create_time'),
-            key: 'createTime',
-            resizable: true
-        },
-        {
-            title: t('common.update_time'),
-            key: 'updateTime',
-            resizable: true
-        },
-    ]
-
-    return { columns }
-}
diff --git a/paimon-web-ui/src/views/system/role/use-constants.tsx 
b/paimon-web-ui/src/views/system/role/use-constants.tsx
new file mode 100644
index 0000000..ce2ae81
--- /dev/null
+++ b/paimon-web-ui/src/views/system/role/use-constants.tsx
@@ -0,0 +1,72 @@
+/* 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 { Role } from "@/api/models/role/types/role"
+import dayjs from "dayjs"
+
+import RoleDetail from "./components/role-detail"
+
+export const useConstants = () => {
+  const { t } = useLocaleHooks()
+  const columns = [
+    {
+      type: 'expand',
+      resizable: true,
+      renderExpand: (row: Role) => {
+        return (
+          <RoleDetail roleRecord={row} />
+        )
+      }
+    },
+    {
+      title: () => t('system.role.role_name'),
+      key: 'roleName',
+      resizable: true
+    },
+    {
+      title: () => t('system.role.role_key'),
+      key: 'roleKey',
+      resizable: true
+    },
+    {
+      title: () => t('system.role.enabled'),
+      key: 'enabled',
+      resizable: true,
+      render: (row: Role) => {
+        return row.enabled ? t('common.yes') : t('common.no')
+      }
+    },
+    {
+      title: () => t('common.create_time'),
+      key: 'createTime',
+      resizable: true,
+      render: (row: Role) => {
+        return row?.createTime ? dayjs(row?.createTime).format('YYYY-MM-DD 
HH:mm') : '-'
+      }
+    },
+    {
+      title: () => t('common.update_time'),
+      key: 'updateTime',
+      resizable: true,
+      render: (row: Role) => {
+        return row?.updateTime ? dayjs(row?.updateTime).format('YYYY-MM-DD 
HH:mm') : '-'
+      }
+    },
+  ]
+
+  return { columns }
+}
diff --git a/paimon-web-ui/src/views/system/role/use-table.ts 
b/paimon-web-ui/src/views/system/role/use-table.ts
index c9d52ea..73980c1 100644
--- a/paimon-web-ui/src/views/system/role/use-table.ts
+++ b/paimon-web-ui/src/views/system/role/use-table.ts
@@ -17,40 +17,44 @@ under the License. */
 
 import { listRoles } from '@/api/models/role';
 export const useTable = () => {
-    const tableVariables = reactive({
-        searchForm: {
-            roleName: ''
-        },
-        pagination: {
-            showQuickJumper: true,
-            showSizePicker: true,
-            pageSize: 10,
-            page: 1,
-            itemCount: 0,
-            onUpdatePage: (page: number) => {
-                tableVariables.pagination.page = page
-                getTableData()
-            },
-        }
-    })
-    const [roleList, useRoleList, { loading }] = listRoles()
-    const getTableData = () => {
-        let params = {
-            roleName: tableVariables.searchForm.roleName,
-            currentPage: tableVariables.pagination.page,
-            pageSize: tableVariables.pagination.pageSize
-        }
-        useRoleList({ params })
-    }
-    const handleResetage = () => {
-        tableVariables.pagination.page = 1
+  const tableVariables = reactive({
+    searchForm: {
+      roleName: ''
+    },
+    pagination: {
+      showQuickJumper: true,
+      showSizePicker: true,
+      pageSize: 10,
+      page: 1,
+      itemCount: 0,
+      onUpdatePage: (page: number) => {
+        tableVariables.pagination.page = page
         getTableData()
+      },
     }
-    return {
-        tableVariables,
-        getTableData,
-        handleResetage,
-        roleList,
-        loading
+  })
+
+  const [roleList, useRoleList, { loading }] = listRoles()
+
+  const getTableData = () => {
+    const params = {
+      roleName: tableVariables.searchForm.roleName,
+      currentPage: tableVariables.pagination.page,
+      pageSize: tableVariables.pagination.pageSize
     }
+    useRoleList({ params })
+  }
+
+  const handleResetage = () => {
+    tableVariables.pagination.page = 1
+    getTableData()
+  }
+
+  return {
+    tableVariables,
+    roleList,
+    loading,
+    getTableData,
+    handleResetage,
+  }
 }

Reply via email to