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

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


The following commit(s) were added to refs/heads/master by this push:
     new ebd258c2446 Add Package Versions section to cluster manager UI (#16534)
ebd258c2446 is described below

commit ebd258c24465c57aaa1a46c5a8bd98adf74f78ca
Author: Xiang Fu <[email protected]>
AuthorDate: Thu Aug 7 23:28:45 2025 -0700

    Add Package Versions section to cluster manager UI (#16534)
    
    * Add Package Versions section to cluster manager UI
    
    - Add new PackageVersions component to display component versions from 
/version API
    - Integrate PackageVersions section below cluster configuration on home page
    - Add getVersions API call and getPackageVersionsData utility method
    - Display package names and versions in searchable table format
    - Add pagination options: 50 and 100 rows per page for all tables
    - UI built and tested successfully
    
    * Address Copilot review feedback: improve type safety and error handling
---
 .../app/components/Homepage/PackageVersions.tsx    | 66 ++++++++++++++++++++++
 .../src/main/resources/app/components/Table.tsx    |  2 +-
 .../src/main/resources/app/interfaces/types.d.ts   |  4 ++
 .../src/main/resources/app/pages/HomePage.tsx      |  2 +
 .../src/main/resources/app/requests/index.ts       |  4 ++
 .../main/resources/app/utils/PinotMethodUtils.ts   | 23 +++++++-
 6 files changed, 98 insertions(+), 3 deletions(-)

diff --git 
a/pinot-controller/src/main/resources/app/components/Homepage/PackageVersions.tsx
 
b/pinot-controller/src/main/resources/app/components/Homepage/PackageVersions.tsx
new file mode 100644
index 00000000000..522f2ac67de
--- /dev/null
+++ 
b/pinot-controller/src/main/resources/app/components/Homepage/PackageVersions.tsx
@@ -0,0 +1,66 @@
+/**
+ * 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 React, { useEffect, useState } from 'react';
+import { TableData } from 'Models';
+import AppLoader from '../AppLoader';
+import CustomizedTables from '../Table';
+import PinotMethodUtils from '../../utils/PinotMethodUtils';
+
+const PackageVersions = () => {
+
+  const [fetching, setFetching] = useState(true);
+  const [error, setError] = useState<string | null>(null);
+  const [tableData, setTableData] = useState<TableData>({
+    columns: [],
+    records: []
+  });
+
+  const fetchData = async () => {
+    try {
+      const result = await PinotMethodUtils.getPackageVersionsData();
+      setTableData(result);
+      setError(null);
+    } catch (err: any) {
+      setError(err?.message || 'Failed to fetch package versions');
+      setTableData({
+        columns: ['Package', 'Version'],
+        records: [],
+        error: err?.message || 'Failed to fetch package versions'
+      });
+    } finally {
+      setFetching(false);
+    }
+  };
+  useEffect(() => {
+    fetchData();
+  }, []);
+
+  return (
+    fetching ? <AppLoader /> :
+    <CustomizedTables
+      title="Package Versions"
+      data={tableData}
+      showSearchBox={true}
+      inAccordionFormat={true}
+    />
+  );
+};
+
+export default PackageVersions;
diff --git a/pinot-controller/src/main/resources/app/components/Table.tsx 
b/pinot-controller/src/main/resources/app/components/Table.tsx
index c6fa7adc522..682949c322f 100644
--- a/pinot-controller/src/main/resources/app/components/Table.tsx
+++ b/pinot-controller/src/main/resources/app/components/Table.tsx
@@ -597,7 +597,7 @@ export default function CustomizedTables({
         </TableContainer>
         {finalData.length > 10 ? (
           <TablePagination
-            rowsPerPageOptions={[5, 10, 25]}
+            rowsPerPageOptions={[5, 10, 25, 50, 100]}
             component="div"
             count={finalData.length}
             rowsPerPage={rowsPerPage}
diff --git a/pinot-controller/src/main/resources/app/interfaces/types.d.ts 
b/pinot-controller/src/main/resources/app/interfaces/types.d.ts
index e38d9d578b0..8670a97b634 100644
--- a/pinot-controller/src/main/resources/app/interfaces/types.d.ts
+++ b/pinot-controller/src/main/resources/app/interfaces/types.d.ts
@@ -275,6 +275,10 @@ declare module 'Models' {
     clusterName: string
   };
 
+  export type PackageVersions = {
+    [packageName: string]: string;
+  };
+
   export type ZKGetList = Array<string>;
 
   export type ZKConfig = {
diff --git a/pinot-controller/src/main/resources/app/pages/HomePage.tsx 
b/pinot-controller/src/main/resources/app/pages/HomePage.tsx
index d07249acd1c..3d0ed1cad3a 100644
--- a/pinot-controller/src/main/resources/app/pages/HomePage.tsx
+++ b/pinot-controller/src/main/resources/app/pages/HomePage.tsx
@@ -25,6 +25,7 @@ import PinotMethodUtils from '../utils/PinotMethodUtils';
 import TenantsListing from '../components/Homepage/TenantsListing';
 import Instances from '../components/Homepage/InstancesTables';
 import ClusterConfig from '../components/Homepage/ClusterConfig';
+import PackageVersions from '../components/Homepage/PackageVersions';
 import useTaskTypesTable from '../components/Homepage/useTaskTypesTable';
 import Skeleton from '@material-ui/lab/Skeleton';
 import { getTenants } from '../requests';
@@ -215,6 +216,7 @@ const HomePage = () => {
       />
       {taskTypesTable}
       <ClusterConfig />
+      <PackageVersions />
     </Grid>
   );
 };
diff --git a/pinot-controller/src/main/resources/app/requests/index.ts 
b/pinot-controller/src/main/resources/app/requests/index.ts
index 7c4d05551cd..4778f950af9 100644
--- a/pinot-controller/src/main/resources/app/requests/index.ts
+++ b/pinot-controller/src/main/resources/app/requests/index.ts
@@ -31,6 +31,7 @@ import {
   TableSchema,
   SQLResult,
   ClusterName,
+  PackageVersions,
   ZKGetList,
   ZKConfig,
   OperationResponse,
@@ -244,6 +245,9 @@ export const getTimeSeriesLanguages = (): 
Promise<AxiosResponse<string[]>> =>
 export const getClusterInfo = (): Promise<AxiosResponse<ClusterName>> =>
   baseApi.get('/cluster/info');
 
+export const getVersions = (): Promise<AxiosResponse<PackageVersions>> =>
+  baseApi.get('/version');
+
 export const zookeeperGetList = (params: string): 
Promise<AxiosResponse<ZKGetList>> =>
   baseApi.get(`/zk/ls?path=${params}`);
 
diff --git a/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts 
b/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts
index 6fcd6a81926..5fe6a329e24 100644
--- a/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts
+++ b/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts
@@ -113,7 +113,8 @@ import {
   getServerToSegmentsCount,
   pauseConsumption,
   resumeConsumption,
-  getPauseStatus
+  getPauseStatus,
+  getVersions
 } from '../requests';
 import { baseApi } from './axios-config';
 import Utils from './Utils';
@@ -1351,6 +1352,23 @@ const getAuthUserEmailFromAccessToken = (
   return email;
 };
 
+// This method is used to display package versions in tabular format on 
cluster manager home page
+// API: /version
+// Expected Output: {columns: [], records: []}
+const getPackageVersionsData = () => {
+  return getVersions().then(({ data }) => {
+    const records = Object.entries(data).map(([packageName, version]) => [
+      packageName,
+      String(version)
+    ]);
+    
+    return {
+      columns: ['Package', 'Version'],
+      records: records
+    };
+  });
+};
+
 export default {
   getTenantsData,
   getAllInstances,
@@ -1448,5 +1466,6 @@ export default {
   resumeConsumptionOp,
   getPauseStatusData,
   fetchServerToSegmentsCountData,
-  getConsumingSegmentsInfoData
+  getConsumingSegmentsInfoData,
+  getPackageVersionsData
 };


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to