You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kyuubi.apache.org by ch...@apache.org on 2023/03/24 03:43:25 UTC

[kyuubi] branch master updated: [KYUUBI #3646][UI] Init Session Statistic Page

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

chengpan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kyuubi.git


The following commit(s) were added to refs/heads/master by this push:
     new 0d5eaa2d0 [KYUUBI #3646][UI] Init Session Statistic Page
0d5eaa2d0 is described below

commit 0d5eaa2d0b6fc58348aef23c7407e7529c2873ab
Author: He Zhao <he...@cisco.com>
AuthorDate: Fri Mar 24 11:43:15 2023 +0800

    [KYUUBI #3646][UI] Init Session Statistic Page
    
    ### _Why are the changes needed?_
    
    Init Session Statistic Page
    
    Close #3646
    
    ### _How was this patch tested?_
    - [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible
    
    - [ ] Add screenshots for manual tests if appropriate
    
    - [ ] [Run test](https://kyuubi.readthedocs.io/en/master/develop_tools/testing.html#running-tests) locally before make a pull request
    
    ![popo_2023-03-20  17-47-24](https://user-images.githubusercontent.com/52876270/226303508-ab55d7d5-62c5-4062-bfab-70c483517e99.jpg)
    
    Closes #4564 from zwangsheng/KYUUBI_3646.
    
    Closes #3646
    
    cbe0842ba [zwangsheng] [KYUUBI #3646] fix style
    930cbb12a [zwangsheng] [KYUUBI #3646] bracket same line
    d2ab1d5fd [zwangsheng] [KYUUBI #3646] Fix i18n about status
    7f059e2df [zwangsheng] [KYUUBI #3646] Fix i18n about status
    452c3ee5a [zwangsheng] [KYUUBI #3646] Remove unused style class
    8967652bc [zwangsheng] [KYUUBI #3646] Add date fns license
    70f2472c2 [zwangsheng] [KYUUBI #3646] install date-fns
    8a3e845ff [zwangsheng] [KYUUBI #3646][UI] Init Session Statistic Page
    
    Lead-authored-by: He Zhao <he...@cisco.com>
    Co-authored-by: zwangsheng <22...@qq.com>
    Signed-off-by: Cheng Pan <ch...@apache.org>
---
 LICENSE-binary                                     |   2 +
 kyuubi-server/web-ui/.eslintrc                     |   3 +
 kyuubi-server/web-ui/package.json                  |   1 +
 kyuubi-server/web-ui/pnpm-lock.yaml                |   7 ++
 .../src/{locales/en_US => api/session}/index.ts    |  16 +++-
 kyuubi-server/web-ui/src/locales/en_US/index.ts    |  13 ++-
 kyuubi-server/web-ui/src/locales/zh_CN/index.ts    |  13 ++-
 kyuubi-server/web-ui/src/router/index.ts           |   2 +
 .../src/{locales/en_US => router/session}/index.ts |  12 ++-
 kyuubi-server/web-ui/src/views/common/use-table.ts |  78 ++++++++++++++++
 .../src/views/layout/components/aside/types.ts     |  10 ++
 .../src/views/session/session-statistics/index.vue | 104 +++++++++++++++++++++
 12 files changed, 254 insertions(+), 7 deletions(-)

diff --git a/LICENSE-binary b/LICENSE-binary
index feab9965e..a52ea95fb 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -456,6 +456,8 @@ is auto-generated by `pnpm licenses list --prod`.
 ├────────────────────────────────────┼──────────────┤
 │ csstype                            │ MIT          │
 ├────────────────────────────────────┼──────────────┤
+│ date-fns                           │ MIT          │
+├────────────────────────────────────┼──────────────┤
 │ dayjs                              │ MIT          │
 ├────────────────────────────────────┼──────────────┤
 │ delayed-stream                     │ MIT          │
diff --git a/kyuubi-server/web-ui/.eslintrc b/kyuubi-server/web-ui/.eslintrc
index ebbf40199..f2bff2cd6 100644
--- a/kyuubi-server/web-ui/.eslintrc
+++ b/kyuubi-server/web-ui/.eslintrc
@@ -69,6 +69,9 @@
       "exports": "never",
       "functions": "never"
     }],
+    "prettier/prettier": ["error", {
+      "bracketSameLine": true
+    }],
     "vue/multi-word-component-names": "off",
     "vue/component-definition-name-casing": "off",
     "vue/require-valid-default-prop": "off",
diff --git a/kyuubi-server/web-ui/package.json b/kyuubi-server/web-ui/package.json
index 63fdc7221..131e69b7f 100644
--- a/kyuubi-server/web-ui/package.json
+++ b/kyuubi-server/web-ui/package.json
@@ -17,6 +17,7 @@
   "dependencies": {
     "@element-plus/icons-vue": "^2.0.9",
     "axios": "^0.27.2",
+    "date-fns": "^2.29.3",
     "element-plus": "^2.2.12",
     "pinia": "^2.0.18",
     "pinia-plugin-persistedstate": "^2.1.1",
diff --git a/kyuubi-server/web-ui/pnpm-lock.yaml b/kyuubi-server/web-ui/pnpm-lock.yaml
index 61fc5124d..1926352ab 100644
--- a/kyuubi-server/web-ui/pnpm-lock.yaml
+++ b/kyuubi-server/web-ui/pnpm-lock.yaml
@@ -12,6 +12,7 @@ specifiers:
   '@vue/eslint-config-typescript': ^11.0.0
   '@vue/test-utils': ^2.0.2
   axios: ^0.27.2
+  date-fns: ^2.29.3
   element-plus: ^2.2.12
   eslint: ^8.21.0
   eslint-plugin-prettier: ^4.2.1
@@ -32,6 +33,7 @@ specifiers:
 dependencies:
   '@element-plus/icons-vue': 2.0.9_vue@3.2.37
   axios: 0.27.2
+  date-fns: 2.29.3
   element-plus: 2.2.13_vue@3.2.37
   pinia: 2.0.18_j6bzmzd4ujpabbp5objtwxyjp4
   pinia-plugin-persistedstate: 2.1.1_pinia@2.0.18
@@ -907,6 +909,11 @@ packages:
       whatwg-url: 11.0.0
     dev: true
 
+  /date-fns/2.29.3:
+    resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==}
+    engines: {node: '>=0.11'}
+    dev: false
+
   /dayjs/1.11.5:
     resolution: {integrity: sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==}
     dev: false
diff --git a/kyuubi-server/web-ui/src/locales/en_US/index.ts b/kyuubi-server/web-ui/src/api/session/index.ts
similarity index 73%
copy from kyuubi-server/web-ui/src/locales/en_US/index.ts
copy to kyuubi-server/web-ui/src/api/session/index.ts
index 92df340d8..6af5a817f 100644
--- a/kyuubi-server/web-ui/src/locales/en_US/index.ts
+++ b/kyuubi-server/web-ui/src/api/session/index.ts
@@ -15,6 +15,18 @@
  * limitations under the License.
  */
 
-export default {
-  test: 'test'
+import request from '@/utils/request'
+
+export function getAllSessions() {
+  return request({
+    url: 'api/v1/sessions',
+    method: 'get'
+  })
+}
+
+export function deleteSession(sessionId: string) {
+  return request({
+    url: `api/v1/sessions/${sessionId}`,
+    method: 'delete'
+  })
 }
diff --git a/kyuubi-server/web-ui/src/locales/en_US/index.ts b/kyuubi-server/web-ui/src/locales/en_US/index.ts
index 92df340d8..99e851651 100644
--- a/kyuubi-server/web-ui/src/locales/en_US/index.ts
+++ b/kyuubi-server/web-ui/src/locales/en_US/index.ts
@@ -16,5 +16,16 @@
  */
 
 export default {
-  test: 'test'
+  test: 'test',
+  user: 'User',
+  client_ip: 'Client IP',
+  kyuubi_instance: 'Kyuubi Instance',
+  session_id: 'Session ID',
+  create_time: 'Create Time',
+  operation: 'Operation',
+  delete_confirm: 'Delete Confirm',
+  message: {
+    delete_succeeded: 'Delete {name} Succeeded',
+    delete_failed: 'Delete {name} Failed'
+  }
 }
diff --git a/kyuubi-server/web-ui/src/locales/zh_CN/index.ts b/kyuubi-server/web-ui/src/locales/zh_CN/index.ts
index 7272109f5..016aaa8e7 100644
--- a/kyuubi-server/web-ui/src/locales/zh_CN/index.ts
+++ b/kyuubi-server/web-ui/src/locales/zh_CN/index.ts
@@ -16,5 +16,16 @@
  */
 
 export default {
-  test: '测试'
+  test: '测试',
+  user: '用户',
+  client_ip: '客户端地址',
+  kyuubi_instance: '服务端地址',
+  session_id: 'Session ID',
+  create_time: '创建时间',
+  operation: '操作',
+  delete_confirm: '确认删除',
+  message: {
+    delete_succeeded: '删除 {name} 成功',
+    delete_failed: '删除 {name} 失败'
+  }
 }
diff --git a/kyuubi-server/web-ui/src/router/index.ts b/kyuubi-server/web-ui/src/router/index.ts
index 207a22d56..4d01da552 100644
--- a/kyuubi-server/web-ui/src/router/index.ts
+++ b/kyuubi-server/web-ui/src/router/index.ts
@@ -20,6 +20,7 @@ import overviewRoutes from './overview'
 import workloadRoutes from './workload'
 import operationRoutes from './operation'
 import contactRoutes from './contact'
+import sessionRoutes from './session'
 
 const routes = [
   {
@@ -36,6 +37,7 @@ const routes = [
     redirect: 'overview',
     children: [
       ...overviewRoutes,
+      ...sessionRoutes,
       ...workloadRoutes,
       ...operationRoutes,
       ...contactRoutes
diff --git a/kyuubi-server/web-ui/src/locales/en_US/index.ts b/kyuubi-server/web-ui/src/router/session/index.ts
similarity index 80%
copy from kyuubi-server/web-ui/src/locales/en_US/index.ts
copy to kyuubi-server/web-ui/src/router/session/index.ts
index 92df340d8..fca49f211 100644
--- a/kyuubi-server/web-ui/src/locales/en_US/index.ts
+++ b/kyuubi-server/web-ui/src/router/session/index.ts
@@ -15,6 +15,12 @@
  * limitations under the License.
  */
 
-export default {
-  test: 'test'
-}
+const routes = [
+  {
+    path: '/session/session-statistics',
+    name: 'session-statistics',
+    component: () => import('@/views/session/session-statistics/index.vue')
+  }
+]
+
+export default routes
diff --git a/kyuubi-server/web-ui/src/views/common/use-table.ts b/kyuubi-server/web-ui/src/views/common/use-table.ts
new file mode 100644
index 000000000..441feb1f1
--- /dev/null
+++ b/kyuubi-server/web-ui/src/views/common/use-table.ts
@@ -0,0 +1,78 @@
+/*
+ * 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 { ref, Ref } from 'vue'
+
+export function useTable() {
+  const list: Ref<any[]> = ref([])
+  const tableData: Ref<any[]> = ref([])
+  const loading = ref(false)
+  const currentPage = ref(1)
+  const pageSize = ref(10)
+  const totalPage = ref(1)
+
+  const handleSizeChange = (val: number) => {
+    if (
+      currentPage.value === 1 ||
+      (currentPage.value > 1 && totalPage.value > (currentPage.value - 1) * val)
+    ) {
+      loading.value = true
+      setTimeout(() => {
+        setTableData()
+      }, 200)
+    }
+  }
+
+  const handleCurrentChange = () => {
+    loading.value = true
+    setTimeout(() => {
+      setTableData()
+    }, 200)
+  }
+
+  const setTableData = () => {
+    tableData.value = [...list.value].splice(
+      (currentPage.value - 1) * pageSize.value,
+      pageSize.value
+    )
+    loading.value = false
+  }
+
+  const getList = (func: Function, data?: any) => {
+    loading.value = true
+    func(data)
+      .then((res: any[]) => (list.value = res || []))
+      .catch(() => (list.value = []))
+      .finally(() => {
+        currentPage.value = 1
+        pageSize.value = 10
+        totalPage.value = list.value.length
+        setTableData()
+      })
+  }
+
+  return {
+    tableData,
+    loading,
+    currentPage,
+    pageSize,
+    totalPage,
+    handleSizeChange,
+    handleCurrentChange,
+    getList
+  }
+}
diff --git a/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts b/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts
index ddd32bef4..71d1d0128 100644
--- a/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts
+++ b/kyuubi-server/web-ui/src/views/layout/components/aside/types.ts
@@ -21,6 +21,16 @@ export const MENUS = [
     icon: 'Odometer',
     router: '/overview'
   },
+  {
+    label: 'Session Management',
+    icon: 'List',
+    children: [
+      {
+        label: 'Session Statistics',
+        router: '/session/session-statistics'
+      }
+    ]
+  },
   {
     label: 'Workload',
     icon: 'List',
diff --git a/kyuubi-server/web-ui/src/views/session/session-statistics/index.vue b/kyuubi-server/web-ui/src/views/session/session-statistics/index.vue
new file mode 100644
index 000000000..40a9b7568
--- /dev/null
+++ b/kyuubi-server/web-ui/src/views/session/session-statistics/index.vue
@@ -0,0 +1,104 @@
+<!--
+* 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.
+-->
+
+<template>
+  <!-- TODO we need search here -->
+  <el-card>
+    <el-table
+      v-loading="loading"
+      :data="tableData"
+      max-height="500px"
+      style="width: 100%">
+      <el-table-column prop="user" :label="$t('user')" width="160px" />
+      <!-- TODO need jump to engine page -->
+      <el-table-column prop="engineId" :label="$t('engine_ip')" width="160px" />
+      <el-table-column prop="ipAddr" :label="$t('client_ip')" width="160px" />
+      <el-table-column
+        prop="kyuubiInstance"
+        :label="$t('kyuubi_instance')"
+        width="180px" />
+      <!-- TODO need jump to session page -->
+      <el-table-column
+        prop="identifier"
+        :label="$t('session_id')"
+        width="300px" />
+      <el-table-column :label="$t('create_time')" width="200">
+        <template #default="scope">
+          {{
+            scope.row.createTime != null && scope.row.createTime > -1
+              ? format(scope.row.createTime, 'yyyy-MM-dd HH:mm:ss')
+              : '-'
+          }}
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" :label="$t('operation')">
+        <template #default="scope">
+          <el-popconfirm
+            :title="$t('delete_confirm')"
+            @confirm="handleDeleteSession(scope.row.identifier)">
+            <template #reference>
+              <span>
+                <el-tooltip
+                  effect="dark"
+                  :content="$t('delete')"
+                  placement="top">
+                  <template #default>
+                    <el-button type="danger" icon="Delete" circle />
+                  </template>
+                </el-tooltip>
+              </span>
+            </template>
+          </el-popconfirm>
+        </template>
+      </el-table-column>
+    </el-table>
+  </el-card>
+</template>
+
+<script lang="ts" setup>
+  import { format } from 'date-fns'
+  import { getAllSessions, deleteSession } from '@/api/session'
+  import { ElMessage } from 'element-plus'
+  import { useI18n } from 'vue-i18n'
+  import { useTable } from '@/views/common/use-table'
+  const { t } = useI18n()
+  const { tableData, loading, getList: _getList } = useTable()
+  const handleDeleteSession = (sessionId: string) => {
+    deleteSession(sessionId)
+      .then(() => {
+        // need add delete success or failed logic after api support
+        ElMessage({
+          message: t('message.delete_succeeded', { name: 'session' }),
+          type: 'success'
+        })
+      })
+      .catch(() => {
+        ElMessage({
+          message: t('message.delete_failed', { name: 'session' }),
+          type: 'error'
+        })
+      })
+      .finally(() => {
+        getList()
+      })
+  }
+  const getList = () => {
+    _getList(getAllSessions)
+  }
+  getList()
+</script>