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]